]> git.mxchange.org Git - friendica-addons.git/commitdiff
Merge remote branch 'upstream/master'
authortony baldwin <tony@baldwinsoftware.com>
Thu, 17 May 2012 04:56:19 +0000 (00:56 -0400)
committertony baldwin <tony@baldwinsoftware.com>
Thu, 17 May 2012 04:56:19 +0000 (00:56 -0400)
279 files changed:
blackout.tgz
blackout/blackout.php
buildtgz
convpath.tgz [new file with mode: 0644]
convpath/README [new file with mode: 0755]
convpath/convpath.php [new file with mode: 0644]
facebook.tgz
facebook/README [deleted file]
facebook/README.md [new file with mode: 0755]
facebook/facebook.php [changed mode: 0755->0644]
facebook_restrict.tgz [new file with mode: 0644]
facebook_restrict/facebook_restrict.php [new file with mode: 0644]
impressum.tgz
impressum/admin.tpl
impressum/impressum.php
jappixmini.tgz [new file with mode: 0644]
jappixmini/MIT.txt [new file with mode: 0644]
jappixmini/README [new file with mode: 0644]
jappixmini/jappix/AUTHORS [new file with mode: 0644]
jappixmini/jappix/COPYING [new file with mode: 0644]
jappixmini/jappix/INSTALL [new file with mode: 0644]
jappixmini/jappix/README [new file with mode: 0644]
jappixmini/jappix/THANKS [new file with mode: 0644]
jappixmini/jappix/VERSION [new file with mode: 0644]
jappixmini/jappix/css/adhoc.css [new file with mode: 0644]
jappixmini/jappix/css/anonymous.css [new file with mode: 0644]
jappixmini/jappix/css/archives.css [new file with mode: 0644]
jappixmini/jappix/css/board.css [new file with mode: 0644]
jappixmini/jappix/css/buddylist.css [new file with mode: 0644]
jappixmini/jappix/css/channel.css [new file with mode: 0644]
jappixmini/jappix/css/directory.css [new file with mode: 0644]
jappixmini/jappix/css/discovery.css [new file with mode: 0644]
jappixmini/jappix/css/favorites.css [new file with mode: 0644]
jappixmini/jappix/css/home.css [new file with mode: 0644]
jappixmini/jappix/css/ie.css [new file with mode: 0644]
jappixmini/jappix/css/images.css [new file with mode: 0644]
jappixmini/jappix/css/inbox.css [new file with mode: 0644]
jappixmini/jappix/css/install.css [new file with mode: 0644]
jappixmini/jappix/css/integratebox.css [new file with mode: 0644]
jappixmini/jappix/css/jquery.datepicker.css [new file with mode: 0644]
jappixmini/jappix/css/main.css [new file with mode: 0644]
jappixmini/jappix/css/manager.css [new file with mode: 0644]
jappixmini/jappix/css/me.css [new file with mode: 0644]
jappixmini/jappix/css/mini-ie.css [new file with mode: 0644]
jappixmini/jappix/css/mini.css [new file with mode: 0644]
jappixmini/jappix/css/mobile.css [new file with mode: 0644]
jappixmini/jappix/css/mucadmin.css [new file with mode: 0644]
jappixmini/jappix/css/myinfos.css [new file with mode: 0644]
jappixmini/jappix/css/options.css [new file with mode: 0644]
jappixmini/jappix/css/others.css [new file with mode: 0644]
jappixmini/jappix/css/pageengine.css [new file with mode: 0644]
jappixmini/jappix/css/pageswitch.css [new file with mode: 0644]
jappixmini/jappix/css/popup.css [new file with mode: 0644]
jappixmini/jappix/css/privacy.css [new file with mode: 0644]
jappixmini/jappix/css/rosterx.css [new file with mode: 0644]
jappixmini/jappix/css/search.css [new file with mode: 0644]
jappixmini/jappix/css/smileys.css [new file with mode: 0644]
jappixmini/jappix/css/stats-svg.css [new file with mode: 0644]
jappixmini/jappix/css/tools.css [new file with mode: 0644]
jappixmini/jappix/css/userinfos.css [new file with mode: 0644]
jappixmini/jappix/css/vcard.css [new file with mode: 0644]
jappixmini/jappix/css/welcome.css [new file with mode: 0644]
jappixmini/jappix/favicon.ico [new file with mode: 0644]
jappixmini/jappix/img/others/blank.gif [new file with mode: 0644]
jappixmini/jappix/img/others/default-avatar.png [new file with mode: 0644]
jappixmini/jappix/img/others/lock.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/animate.gif [new file with mode: 0644]
jappixmini/jappix/img/sprites/animate.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/background.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/browsers.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/buttons.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/home.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/install.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/logs.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/manager.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/me.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/mini.gif [new file with mode: 0644]
jappixmini/jappix/img/sprites/mini.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/mobile.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/smileys.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/talk.png [new file with mode: 0644]
jappixmini/jappix/img/sprites/welcome.png [new file with mode: 0644]
jappixmini/jappix/img/wait/wait-big.gif [new file with mode: 0644]
jappixmini/jappix/img/wait/wait-medium.png [new file with mode: 0644]
jappixmini/jappix/img/wait/wait-small.gif [new file with mode: 0644]
jappixmini/jappix/js/adhoc.js [new file with mode: 0644]
jappixmini/jappix/js/anonymous.js [new file with mode: 0644]
jappixmini/jappix/js/archives.js [new file with mode: 0644]
jappixmini/jappix/js/audio.js [new file with mode: 0644]
jappixmini/jappix/js/autocompletion.js [new file with mode: 0644]
jappixmini/jappix/js/avatar.js [new file with mode: 0644]
jappixmini/jappix/js/base64.js [new file with mode: 0644]
jappixmini/jappix/js/board.js [new file with mode: 0644]
jappixmini/jappix/js/browser-detect.js [new file with mode: 0644]
jappixmini/jappix/js/bubble.js [new file with mode: 0644]
jappixmini/jappix/js/caps.js [new file with mode: 0644]
jappixmini/jappix/js/chat.js [new file with mode: 0644]
jappixmini/jappix/js/chatstate.js [new file with mode: 0644]
jappixmini/jappix/js/common.js [new file with mode: 0644]
jappixmini/jappix/js/connection.js [new file with mode: 0644]
jappixmini/jappix/js/constants.js [new file with mode: 0644]
jappixmini/jappix/js/dataform.js [new file with mode: 0644]
jappixmini/jappix/js/datastore.js [new file with mode: 0644]
jappixmini/jappix/js/date.js [new file with mode: 0644]
jappixmini/jappix/js/directory.js [new file with mode: 0644]
jappixmini/jappix/js/discovery.js [new file with mode: 0644]
jappixmini/jappix/js/error.js [new file with mode: 0644]
jappixmini/jappix/js/favorites.js [new file with mode: 0644]
jappixmini/jappix/js/features.js [new file with mode: 0644]
jappixmini/jappix/js/filter.js [new file with mode: 0644]
jappixmini/jappix/js/groupchat.js [new file with mode: 0644]
jappixmini/jappix/js/home.js [new file with mode: 0644]
jappixmini/jappix/js/httpauth.js [new file with mode: 0644]
jappixmini/jappix/js/inbox.js [new file with mode: 0644]
jappixmini/jappix/js/integratebox.js [new file with mode: 0644]
jappixmini/jappix/js/interface.js [new file with mode: 0644]
jappixmini/jappix/js/iq.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.datepicker.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.form.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.placeholder.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.textrange.js [new file with mode: 0644]
jappixmini/jappix/js/jquery.timers.js [new file with mode: 0644]
jappixmini/jappix/js/jsjac.js [new file with mode: 0644]
jappixmini/jappix/js/jxhr.js [new file with mode: 0644]
jappixmini/jappix/js/links.js [new file with mode: 0644]
jappixmini/jappix/js/me.js [new file with mode: 0644]
jappixmini/jappix/js/message.js [new file with mode: 0644]
jappixmini/jappix/js/microblog.js [new file with mode: 0644]
jappixmini/jappix/js/mini.js [new file with mode: 0644]
jappixmini/jappix/js/mobile.js [new file with mode: 0644]
jappixmini/jappix/js/mucadmin.js [new file with mode: 0644]
jappixmini/jappix/js/music.js [new file with mode: 0644]
jappixmini/jappix/js/name.js [new file with mode: 0644]
jappixmini/jappix/js/notification.js [new file with mode: 0644]
jappixmini/jappix/js/oob.js [new file with mode: 0644]
jappixmini/jappix/js/options.js [new file with mode: 0644]
jappixmini/jappix/js/pep.js [new file with mode: 0644]
jappixmini/jappix/js/popup.js [new file with mode: 0644]
jappixmini/jappix/js/presence.js [new file with mode: 0644]
jappixmini/jappix/js/privacy.js [new file with mode: 0644]
jappixmini/jappix/js/receipts.js [new file with mode: 0644]
jappixmini/jappix/js/roster.js [new file with mode: 0644]
jappixmini/jappix/js/rosterx.js [new file with mode: 0644]
jappixmini/jappix/js/search.js [new file with mode: 0644]
jappixmini/jappix/js/smileys.js [new file with mode: 0644]
jappixmini/jappix/js/storage.js [new file with mode: 0644]
jappixmini/jappix/js/talk.js [new file with mode: 0644]
jappixmini/jappix/js/tooltip.js [new file with mode: 0644]
jappixmini/jappix/js/userinfos.js [new file with mode: 0644]
jappixmini/jappix/js/utilities.js [new file with mode: 0644]
jappixmini/jappix/js/vcard.js [new file with mode: 0644]
jappixmini/jappix/js/welcome.js [new file with mode: 0644]
jappixmini/jappix/js/xmpplinks.js [new file with mode: 0644]
jappixmini/jappix/lang/ar/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/ar/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/bg/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/bg/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/cs/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/cs/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/de/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/de/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/en/LC_MESSAGES/main.pot [new file with mode: 0644]
jappixmini/jappix/lang/eo/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/eo/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/es/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/es/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/et/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/et/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/fa/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/fa/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/fr/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/fr/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/hu/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/hu/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/id/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/id/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/it/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/it/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/ja/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/ja/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/nl/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/nl/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/oc/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/oc/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/pl/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/pl/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/ru/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/ru/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/sk/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/sk/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/sv/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/sv/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/uk/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/uk/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/lang/zh/LC_MESSAGES/main.mo [new file with mode: 0644]
jappixmini/jappix/lang/zh/LC_MESSAGES/main.po [new file with mode: 0644]
jappixmini/jappix/php/avatar-upload.php [new file with mode: 0644]
jappixmini/jappix/php/bosh.php [new file with mode: 0644]
jappixmini/jappix/php/desktop.php [new file with mode: 0644]
jappixmini/jappix/php/download-chat.php [new file with mode: 0644]
jappixmini/jappix/php/drawsvgchart.php [new file with mode: 0644]
jappixmini/jappix/php/file-share.php [new file with mode: 0644]
jappixmini/jappix/php/form-hosts.php [new file with mode: 0644]
jappixmini/jappix/php/form-main.php [new file with mode: 0644]
jappixmini/jappix/php/form-users.php [new file with mode: 0644]
jappixmini/jappix/php/functions-get.php [new file with mode: 0644]
jappixmini/jappix/php/functions-manager.php [new file with mode: 0644]
jappixmini/jappix/php/functions.php [new file with mode: 0644]
jappixmini/jappix/php/generate-chat.php [new file with mode: 0644]
jappixmini/jappix/php/geolocation.php [new file with mode: 0644]
jappixmini/jappix/php/get-store.php [new file with mode: 0644]
jappixmini/jappix/php/get.php [new file with mode: 0644]
jappixmini/jappix/php/gettext.php [new file with mode: 0644]
jappixmini/jappix/php/install.php [new file with mode: 0644]
jappixmini/jappix/php/jsmin.php [new file with mode: 0644]
jappixmini/jappix/php/manager.php [new file with mode: 0644]
jappixmini/jappix/php/mobile-detect.php [new file with mode: 0644]
jappixmini/jappix/php/mobile.php [new file with mode: 0644]
jappixmini/jappix/php/music-search.php [new file with mode: 0644]
jappixmini/jappix/php/post-design.php [new file with mode: 0644]
jappixmini/jappix/php/post-hosts.php [new file with mode: 0644]
jappixmini/jappix/php/post-main.php [new file with mode: 0644]
jappixmini/jappix/php/post-store.php [new file with mode: 0644]
jappixmini/jappix/php/post-users.php [new file with mode: 0644]
jappixmini/jappix/php/read-design.php [new file with mode: 0644]
jappixmini/jappix/php/read-hosts.php [new file with mode: 0644]
jappixmini/jappix/php/read-main.php [new file with mode: 0644]
jappixmini/jappix/php/send.php [new file with mode: 0644]
jappixmini/jappix/php/static.php [new file with mode: 0644]
jappixmini/jappix/php/stats-svg.php [new file with mode: 0644]
jappixmini/jappix/php/store-tree.php [new file with mode: 0644]
jappixmini/jappix/php/upload.php [new file with mode: 0644]
jappixmini/jappix/php/vars-design.php [new file with mode: 0644]
jappixmini/jappix/php/vars-hosts.php [new file with mode: 0644]
jappixmini/jappix/php/vars-main.php [new file with mode: 0644]
jappixmini/jappix/php/vars-store.php [new file with mode: 0644]
jappixmini/jappix/snd/new-chat.oga [new file with mode: 0644]
jappixmini/jappix/snd/notification.oga [new file with mode: 0644]
jappixmini/jappix/snd/receive-message.oga [new file with mode: 0644]
jappixmini/jappix/xml/anonymous.xml [new file with mode: 0644]
jappixmini/jappix/xml/desktop.xml [new file with mode: 0644]
jappixmini/jappix/xml/install.xml [new file with mode: 0644]
jappixmini/jappix/xml/manager.xml [new file with mode: 0644]
jappixmini/jappix/xml/mini.xml [new file with mode: 0644]
jappixmini/jappix/xml/mobile.xml [new file with mode: 0644]
jappixmini/jappixmini.php [new file with mode: 0644]
jappixmini/lib.js [new file with mode: 0644]
jappixmini/proxy.php [new file with mode: 0644]
mathjax.tgz [new file with mode: 0644]
mathjax/README [new file with mode: 0644]
mathjax/admin.tpl [new file with mode: 0644]
mathjax/mathjax.php [new file with mode: 0644]
nsfw.tgz
nsfw/nsfw.php
page.tgz
page/page.php
pages.tgz [deleted file]
posterous.tgz
posterous/posterous.php
privacy_image_cache/README.md [new file with mode: 0644]
privacy_image_cache/privacy_image_cache.php [new file with mode: 0644]
smiley_pack.tgz
smiley_pack/icons/animals/cat.gif
smiley_pack/icons/tired/yawn.gif [new file with mode: 0644]
smiley_pack/smiley_pack.php
smilies_adult.tgz
statusnet.tgz
statusnet/statusnet.php
twitter.tgz
twitter/README
twitter/twitter.php
widgets.tgz
widgets/widget_friendheader.php [new file with mode: 0644]
wppost.tgz
wppost/wppost.css
wppost/wppost.php

index ef87ed74bd9f55b564194a60aa3c4fd934ffe86c..4b5a5d312d391537ef64ea909cf8ecdcffe15f0c 100644 (file)
Binary files a/blackout.tgz and b/blackout.tgz differ
index ffd59dca64991d1fc131d898e3b3feb54381b7d6..2cb7c041d6cf3dff8f60486a10f2e4a4d879ffd4 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * Name: blackout
- * Description: Blackout your ~friendica node during a given period
+ * Description: Blackout your ~friendica node during a given period, requires PHP >= 5.3
  * License: MIT
  * Version: 1.0
  * Author: Tobias Diekershoff <https://diekershoff.homeunix.net/friendika/~tobias>
@@ -62,6 +62,10 @@ function blackout_redirect ($a, $b) {
     if (local_user()) {
         return true;
     }
+
+       if (! (version_compare(PHP_VERSION, '5.3.0') >= 0))
+               return true;
+
     // else...
     $mystart = get_config('blackout','begindate');
     $myend   = get_config('blackout','enddate');
index 37c734f87564ffbaba04f6a0ca6f0f1afc469947..94eee46443e20904f0b3bdb45937de79575ec4bb 100755 (executable)
--- a/buildtgz
+++ b/buildtgz
@@ -12,13 +12,13 @@ for a in $SUBDIRS; do
        if [[ ! -f $TGZ ]]; then
                echo "Building: " $TGZ
 #              git log $a > $a/$a.log
-               tar zcvf $TGZ $a
+               tar zcvf $TGZ --exclude=.[a-z]* $a
        else
                TOUCHED=`find $a -cnewer $TGZ`
                if [[ -n $TOUCHED ]]; then
                        echo "Building: " $TGZ
 #                      git log $a > $a/$a.log
-                       tar zcvf $TGZ $a
+                       tar zcvf $TGZ --exclude=.[a-z]* $a
                fi
        fi
 done
diff --git a/convpath.tgz b/convpath.tgz
new file mode 100644 (file)
index 0000000..2c43d3d
Binary files /dev/null and b/convpath.tgz differ
diff --git a/convpath/README b/convpath/README
new file mode 100755 (executable)
index 0000000..9d1c307
--- /dev/null
@@ -0,0 +1,7 @@
+convpath
+
+This addon converts all internal paths according to the current scheme. 
+
+That means that if a page is called via https then all internal links are also converted into https.
+
+Same happens when you call your page with http.
diff --git a/convpath/convpath.php b/convpath/convpath.php
new file mode 100644 (file)
index 0000000..e5dc0b3
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Name: Convert Paths
+ * Description: Converts all internal paths according to the current scheme (http or https)
+ * Version: 1.0
+ * Author: Michael Vogel <https://pirati.ca/profile/heluecht>
+ * 
+ */
+
+function convpath_install() {
+       register_hook('page_end', 'addon/convpath/convpath.php', 'convpath_page_end');
+       register_hook('page_header', 'addon/convpath/convpath.php', 'convpath_page_header');
+}
+
+
+function convpath_uninstall() {
+       unregister_hook('page_end', 'addon/convpath/convpath.php', 'convpath_page_end');
+       unregister_hook('page_header', 'addon/convpath/convpath.php', 'convpath_page_header');
+}
+
+function convpath_page_header(&$a, &$o){
+       $o = convpath_convert($o);
+}
+
+function convpath_page_end(&$a, &$o){
+       $o = convpath_convert($o);
+       $a->page['aside'] = convpath_convert($a->page['aside']);
+}
+
+/*
+Converts a given path according to the current scheme
+*/
+function convpath_convert($path) {
+       global $a;
+
+       if ($path == "")
+               return("");
+
+       $ssl = (substr($a->get_baseurl(), 0, 8) == "https://");
+
+       if ($ssl) {
+               $search = "http://".$a->get_hostname();
+               $replace = "https://".$a->get_hostname();
+       } else {
+               $search = "https://".$a->get_hostname();
+               $replace = "http://".$a->get_hostname();
+       }
+       $searcharr = array("src='".$search, 'src="'.$search);
+       $replacearr = array("src='".$replace, 'src="'.$replace);
+       $path = str_replace($searcharr, $replacearr, $path);
+
+       //$path = str_replace($search, $replace, $path);
+
+       return($path);
+}
index 2b643e70c057f8053eb7e0dcb4798211e7ac3a6f..ca4a858c7fb022159cddbd77edff2588e7ce006c 100644 (file)
Binary files a/facebook.tgz and b/facebook.tgz differ
diff --git a/facebook/README b/facebook/README
deleted file mode 100755 (executable)
index b68ba3d..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-Installing the Friendica/Facebook connector
-
-1. Visit https://developers.facebook.com/apps to register an app.
-    a) Click "Create a new app"
-    b) We'd be very happy if you include "Friendica" in the application name
-       to increase name recognition.  
-    c) Edit your app settings on the setup page.  The Friendica icons are present
-       in the images directory and may be uploaded as a Facebook app icon.  Use 
-       images/friendica-16.jpg for the Icon and images/Friendica-128.jpg for the logo.
-    d) In the App Display name enter the name of your app (this should default to the
-       name you chose in part a).
-    e) Enter YourDomain.com in the App Domain field and hit return.
-    f) In "Select how your app connects with Facebook select "Website" and enter the 
-       full URL to your Friendica install including HTTPS and a trailing slash.
-
-2.    Enable the Facebook plugin by clicking on the icon next to it's name on the plugin
-      page of your admin panel.
-   b) return to the Facebook plugin page in your admin panel, and fill in the App-ID
-      and Application Secret settings you got from Facebook.
-   c) Click save.
-   d) Finally, return to the Facebook settings page, and activate real-time updates.
-
-       i. If you for any reason prefer to use a configuration file instead of the admin panels, 
-           Activate the plugin by including it in .htconfig.php, e.g.
-           
-               $a->config['system']['addon'] = 'plugin1,plugin2,facebook';
-       
-           and set the following values:
-               $a->config['facebook']['appid'] = 'xxxxxxxxxxx';
-               $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx';
-
-           Replace with the settings Facebook gives you.
-       
-
-3.    To use the Facebook plugin, visit the "connector settings" area of your settings
-      page.  Click "Install Facebook Connector".  
-4.    This will ask you to login to Facebook and allow the plugin to do it's stuff.  
-      Allow it to do so.
-5.    You're done. To turn it off visit the Plugin Settings page again and
-      'Remove Facebook posting'.
-
-Vidoes and embeds will not be posted if there is no other content. Links 
-and images will be converted to a format suitable for the Facebook API and 
-long posts truncated - with a link to view the full post. 
-
-Facebook contacts will not be able to view private photos, as they are not able to
-authenticate to your site to establish identity. We will address this 
-in a future release.
-
-Info: please make sure that you understand all aspects due to Friendica's 
-default licence which is: MIT License (further info:
-https://github.com/friendica/friendica/blob/master/LICENSE)
diff --git a/facebook/README.md b/facebook/README.md
new file mode 100755 (executable)
index 0000000..a02461e
--- /dev/null
@@ -0,0 +1,15 @@
+Installing the Friendica/Facebook connector
+
+Detailed instructions how to use this plugin can be found at
+the [How to: Friendica's Facebook Connector](https://github.com/friendica/friendica/wiki/How-to:-Friendica%E2%80%99s-Facebook-connector) page.
+
+Vidoes and embeds will not be posted if there is no other content. Links 
+and images will be converted to a format suitable for the Facebook API and 
+long posts truncated - with a link to view the full post. 
+
+Facebook contacts will not be able to view private photos, as they are not able to
+authenticate to your site to establish identity. We will address this 
+in a future release.
+
+Info: please make sure that you understand all aspects due to Friendica's 
+default licence which is: [MIT License](https://github.com/friendica/friendica/blob/master/LICENSE)
old mode 100755 (executable)
new mode 100644 (file)
index cb1fdee..2c48c7a
@@ -1,7 +1,7 @@
 <?php
 /**
  * Name: Facebook Connector
- * Version: 1.1
+ * Version: 1.3
  * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
  *         Tobias Hößl <https://github.com/CatoTH/>
  */
@@ -9,33 +9,8 @@
 /**
  * Installing the Friendica/Facebook connector
  *
- * 1. register an API key for your site from developer.facebook.com
- *   a. We'd be very happy if you include "Friendica" in the application name
- *      to increase name recognition. The Friendica icons are also present
- *      in the images directory and may be uploaded as a Facebook app icon.
- *      Use images/friendica-16.jpg for the Icon and images/friendica-128.jpg for the Logo.
- *   b. The url should be your site URL with a trailing slash.
- *      Friendica is a software application and does not require a Privacy Policy 
- *      or Terms of Service, though your installation of it might. Facebook may require
- *      that you provide a Privacy Policy, which we find ironic.  
- *   c. Set the following values in your .htconfig.php file
- *         $a->config['facebook']['appid'] = 'xxxxxxxxxxx';
- *         $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx';
- *      Replace with the settings Facebook gives you.
- *   d. Navigate to Set Web->Site URL & Domain -> Website Settings.  Set 
- *      Site URL to yoursubdomain.yourdomain.com. Set Site Domain to your 
- *      yourdomain.com.
- * 2. Visit the Facebook Settings section of the "Settings->Plugin Settings" page.
- *    and click 'Install Facebook Connector'.
- * 3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page.
- *    and click 'Install Facebook Connector'.
- * 4. This will ask you to login to Facebook and grant permission to the 
- *    plugin to do its stuff. Allow it to do so. 
- * 5. Optional step: If you want to use Facebook Real Time Updates (so new messages
- *    and new contacts are added ~1min after they are postet / added on FB), go to
- *    Settings -> plugins -> facebook and press the "Activate Real-Time Updates"-button.
- * 6. You're done. To turn it off visit the Plugin Settings page again and
- *    'Remove Facebook posting'.
+ * Detailed instructions how to use this plugin can be found at
+ * https://github.com/friendica/friendica/wiki/How-to:-Friendica%E2%80%99s-Facebook-connector
  *
  * Vidoes and embeds will not be posted if there is no other content. Links 
  * and images will be converted to a format suitable for the Facebook API and 
@@ -58,6 +33,7 @@ define('FACEBOOK_MAXPOSTLEN', 63206);
 define('FACEBOOK_SESSION_ERR_NOTIFICATION_INTERVAL', 259200); // 3 days
 define('FACEBOOK_DEFAULT_POLL_INTERVAL', 60); // given in minutes
 define('FACEBOOK_MIN_POLL_INTERVAL', 5);
+define('FACEBOOK_RTU_ERR_MAIL_AFTER_MINUTES', 180); // 3 hours
 
 require_once('include/security.php');
 
@@ -96,8 +72,11 @@ function facebook_module() {}
 // If a->argv[1] is a nickname, this is a callback from Facebook oauth requests.
 // If $_REQUEST["realtime_cb"] is set, this is a callback from the Real-Time Updates API
 
+/**
+ * @param App $a
+ */
 function facebook_init(&$a) {
-       
+
        if (x($_REQUEST, "realtime_cb") && x($_REQUEST, "realtime_cb")) {
                logger("facebook_init: Facebook Real-Time callback called", LOGGER_DEBUG);
                
@@ -191,7 +170,7 @@ function facebook_init(&$a) {
                $r = q("SELECT `uid` FROM `user` WHERE `nickname` = '%s' LIMIT 1",
                                dbesc($nick)
                );
-       if(! count($r))
+       if(!(isset($r) && count($r)))
                return;
 
        $uid           = $r[0]['uid'];
@@ -233,6 +212,9 @@ function facebook_init(&$a) {
 }
 
 
+/**
+ * @param int $uid
+ */
 function fb_get_self($uid) {
        $access_token = get_pconfig($uid,'facebook','access_token');
        if(! $access_token)
@@ -244,133 +226,165 @@ function fb_get_self($uid) {
        }
 }
 
-function fb_get_friends_sync_new($uid, $access_token, $person) {
-       $link = 'http://facebook.com/profile.php?id=' . $person->id;
-       
-       $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
-               intval($uid),
-               dbesc($link)
-       );
-       
-       if (count($r) == 0) {
-               logger('fb_get_friends: new contact found: ' . $link, LOGGER_DEBUG);
-               
-               fb_get_friends_sync_full($uid, $access_token, $person);
-       }
-}
-
-function fb_get_friends_sync_full($uid, $access_token, $person) {
-       $s = fetch_url('https://graph.facebook.com/' . $person->id . '?access_token=' . $access_token);
-       if($s) {
-               $jp = json_decode($s);
-               logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
-
-               // always use numeric link for consistency
-
-               $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
-
-               // If its a page then set the first name from the username
-               if (!$jp->first_name and $jp->username)
-                       $jp->first_name = $jp->username;
-
-               // check if we already have a contact
+/**
+ * @param int $uid
+ * @param string $access_token
+ * @param array $persons
+ */
+function fb_get_friends_sync_new($uid, $access_token, $persons) {
+    $persons_todo = array();
+    foreach ($persons as $person) {
+        $link = 'http://facebook.com/profile.php?id=' . $person->id;
+
+        $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+            intval($uid),
+            dbesc($link)
+        );
+
+        if (count($r) == 0) {
+            logger('fb_get_friends: new contact found: ' . $link, LOGGER_DEBUG);
+            $persons_todo[] = $person;
+        }
 
-               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
-                       intval($uid),
-                       dbesc($jp->link)
-               );                      
+        if (count($persons_todo) > 0) fb_get_friends_sync_full($uid, $access_token, $persons_todo);
+    }
+}
 
-               if(count($r)) {
+/**
+ * @param int $uid
+ * @param object $contact
+ */
+function fb_get_friends_sync_parsecontact($uid, $contact) {
+    $contact->link = 'http://facebook.com/profile.php?id=' . $contact->id;
+
+    // If its a page then set the first name from the username
+    if (!$contact->first_name and $contact->username)
+        $contact->first_name = $contact->username;
+
+    // check if we already have a contact
+
+    $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+        intval($uid),
+        dbesc($contact->link)
+    );
+
+    if(count($r)) {
+
+        // check that we have all the photos, this has been known to fail on occasion
+
+        if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {
+            require_once("Photo.php");
+
+            $photos = import_profile_photo('https://graph.facebook.com/' . $contact->id . '/picture', $uid, $r[0]['id']);
+
+            q("UPDATE `contact` SET `photo` = '%s',
+                                        `thumb` = '%s',
+                                        `micro` = '%s',
+                                        `name-date` = '%s',
+                                        `uri-date` = '%s',
+                                        `avatar-date` = '%s'
+                                        WHERE `id` = %d LIMIT 1
+                                ",
+                dbesc($photos[0]),
+                dbesc($photos[1]),
+                dbesc($photos[2]),
+                dbesc(datetime_convert()),
+                dbesc(datetime_convert()),
+                dbesc(datetime_convert()),
+                intval($r[0]['id'])
+            );
+        }
+        return;
+    }
+    else {
+
+        // create contact record
+        q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
+                                `name`, `nick`, `photo`, `network`, `rel`, `priority`,
+                                `writable`, `blocked`, `readonly`, `pending` )
+                                VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
+            intval($uid),
+            dbesc(datetime_convert()),
+            dbesc($contact->link),
+            dbesc(normalise_link($contact->link)),
+            dbesc(''),
+            dbesc(''),
+            dbesc($contact->id),
+            dbesc('facebook ' . $contact->id),
+            dbesc($contact->name),
+            dbesc(($contact->nickname) ? $contact->nickname : strtolower($contact->first_name)),
+            dbesc('https://graph.facebook.com/' . $contact->id . '/picture'),
+            dbesc(NETWORK_FACEBOOK),
+            intval(CONTACT_IS_FRIEND),
+            intval(1),
+            intval(1)
+        );
+    }
 
-                       // check that we have all the photos, this has been known to fail on occasion
-
-                       if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {  
-                               require_once("Photo.php");
-
-                               $photos = import_profile_photo('https://graph.facebook.com/' . $jp->id . '/picture', $uid, $r[0]['id']);
-
-                               $r = q("UPDATE `contact` SET `photo` = '%s', 
-                                       `thumb` = '%s',
-                                       `micro` = '%s', 
-                                       `name-date` = '%s', 
-                                       `uri-date` = '%s', 
-                                       `avatar-date` = '%s'
-                                       WHERE `id` = %d LIMIT 1
-                               ",
-                                       dbesc($photos[0]),
-                                       dbesc($photos[1]),
-                                       dbesc($photos[2]),
-                                       dbesc(datetime_convert()),
-                                       dbesc(datetime_convert()),
-                                       dbesc(datetime_convert()),
-                                       intval($r[0]['id'])
-                               );                      
-                       }       
-                       return;
-               }
-               else {
+    $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
+        dbesc($contact->link),
+        intval($uid)
+    );
 
-                       // create contact record 
-                       $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`, 
-                               `name`, `nick`, `photo`, `network`, `rel`, `priority`,
-                               `writable`, `blocked`, `readonly`, `pending` )
-                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
-                               intval($uid),
-                               dbesc(datetime_convert()),
-                               dbesc($jp->link),
-                               dbesc(normalise_link($jp->link)),
-                               dbesc(''),
-                               dbesc(''),
-                               dbesc($jp->id),
-                               dbesc('facebook ' . $jp->id),
-                               dbesc($jp->name),
-                               dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
-                               dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
-                               dbesc(NETWORK_FACEBOOK),
-                               intval(CONTACT_IS_FRIEND),
-                               intval(1),
-                               intval(1)
-                       );
-               }
+    if(! count($r)) {
+        return;
+    }
 
-               $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
-                       dbesc($jp->link),
-                       intval($uid)
-               );
+    $contact_id  = $r[0]['id'];
+
+    require_once("Photo.php");
+
+    $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
+
+    q("UPDATE `contact` SET `photo` = '%s',
+                        `thumb` = '%s',
+                        `micro` = '%s',
+                        `name-date` = '%s',
+                        `uri-date` = '%s',
+                        `avatar-date` = '%s'
+                        WHERE `id` = %d LIMIT 1
+                ",
+        dbesc($photos[0]),
+        dbesc($photos[1]),
+        dbesc($photos[2]),
+        dbesc(datetime_convert()),
+        dbesc(datetime_convert()),
+        dbesc(datetime_convert()),
+        intval($contact_id)
+    );
+}
 
-               if(! count($r)) {
-                       return;
-               }
+/**
+ * @param int $uid
+ * @param string $access_token
+ * @param array $persons
+ */
+function fb_get_friends_sync_full($uid, $access_token, $persons) {
+    if (count($persons) == 0) return;
+    $nums = Ceil(count($persons) / 50);
+    for ($i = 0; $i < $nums; $i++) {
+        $batch_request = array();
+        for ($j = $i * 50; $j < ($i+1) * 50 && $j < count($persons); $j++) $batch_request[] = array('method'=>'GET', 'relative_url'=>$persons[$j]->id);
+        $s = post_url('https://graph.facebook.com/', array('access_token' => $access_token, 'batch' => json_encode($batch_request)));
+        if($s) {
+            $results = json_decode($s);
+            logger('fb_get_friends: info: ' . print_r($results,true), LOGGER_DATA);
+            foreach ($results as $contact) {
+                if ($contact->code != 200) logger('fb_get_friends: not found: ' . print_r($contact,true), LOGGER_DEBUG);
+                else fb_get_friends_sync_parsecontact($uid, json_decode($contact->body));
+            }
+        }
+    }
+}
 
-               $contact = $r[0];
-               $contact_id  = $r[0]['id'];
-
-               require_once("Photo.php");
-
-               $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
-
-               $r = q("UPDATE `contact` SET `photo` = '%s', 
-                       `thumb` = '%s',
-                       `micro` = '%s', 
-                       `name-date` = '%s', 
-                       `uri-date` = '%s', 
-                       `avatar-date` = '%s'
-                       WHERE `id` = %d LIMIT 1
-               ",
-                       dbesc($photos[0]),
-                       dbesc($photos[1]),
-                       dbesc($photos[2]),
-                       dbesc(datetime_convert()),
-                       dbesc(datetime_convert()),
-                       dbesc(datetime_convert()),
-                       intval($contact_id)
-               );                      
 
-       }
-}
 
 // if $fullsync is true, only new contacts are searched for
 
+/**
+ * @param int $uid
+ * @param bool $fullsync
+ */
 function fb_get_friends($uid, $fullsync = true) {
 
        $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
@@ -394,22 +408,32 @@ function fb_get_friends($uid, $fullsync = true) {
                logger('facebook: fb_get_friends: json: ' . print_r($j,true), LOGGER_DATA);
                if(! $j->data)
                        return;
-               foreach($j->data as $person)
-                       if ($fullsync)
-                               fb_get_friends_sync_full($uid, $access_token, $person);
-                       else
-                               fb_get_friends_sync_new($uid, $access_token, $person);
+
+           $persons_todo = array();
+        foreach($j->data as $person) $persons_todo[] = $person;
+
+        if ($fullsync)
+            fb_get_friends_sync_full($uid, $access_token, $persons_todo);
+        else
+            fb_get_friends_sync_new($uid, $access_token, $persons_todo);
        }
 }
 
 // This is the POST method to the facebook settings page
 // Content is posted to Facebook in the function facebook_post_hook() 
 
+/**
+ * @param App $a
+ */
 function facebook_post(&$a) {
 
        $uid = local_user();
        if($uid){
 
+
+               $fb_limited = get_config('facebook','restrict');
+
+
                $value = ((x($_POST,'post_by_default')) ? intval($_POST['post_by_default']) : 0);
                set_pconfig($uid,'facebook','post_by_default', $value);
 
@@ -425,7 +449,13 @@ function facebook_post(&$a) {
                set_pconfig($uid,'facebook','blocked_apps',escape_tags(trim($_POST['blocked_apps'])));
 
                $linkvalue = ((x($_POST,'facebook_linking')) ? intval($_POST['facebook_linking']) : 0);
-               set_pconfig($uid,'facebook','no_linking', (($linkvalue) ? 0 : 1));
+
+               if($fb_limited) {
+                       if($linkvalue == 0)
+                               set_pconfig($uid,'facebook','no_linking', 1);
+               }
+               else    
+                       set_pconfig($uid,'facebook','no_linking', (($linkvalue) ? 0 : 1));
 
                // FB linkage was allowed but has just been turned off - remove all FB contacts and posts
 
@@ -455,6 +485,10 @@ function facebook_post(&$a) {
 
 // Facebook settings form
 
+/**
+ * @param App $a
+ * @return string
+ */
 function facebook_content(&$a) {
 
        if(! local_user()) {
@@ -472,13 +506,15 @@ function facebook_content(&$a) {
                info( t('Updating contacts') . EOL);
        }
 
+
+       $fb_limited = get_config('facebook','restrict');
+
        $o = '';
        
        $fb_installed = false;
        if (get_pconfig(local_user(),'facebook','post')) {
                $access_token = get_pconfig(local_user(),'facebook','access_token');
                if ($access_token) {
-                       $private_wall = intval(get_pconfig($uid,'facebook','private_wall'));
                        $s = fetch_url('https://graph.facebook.com/me/feed?access_token=' . $access_token);
                        if($s) {
                                $j = json_decode($s);
@@ -494,7 +530,7 @@ function facebook_content(&$a) {
                return '';
        }
 
-       $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="' 
+       $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'
                . $a->get_baseurl() . '/addon/facebook/facebook.css' . '" media="all" />' . "\r\n";
 
        $o .= '<h3>' . t('Facebook Connect') . '</h3>';
@@ -526,6 +562,15 @@ function facebook_content(&$a) {
 
                $no_linking = get_pconfig(local_user(),'facebook','no_linking');
                $checked = (($no_linking) ? '' : ' checked="checked" ');
+               if($fb_limited) {
+                       if($no_linking) {
+                               $o .= EOL . '<strong>' . t('Facebook friend linking has been disabled on this site. The following settings will have no effect.') . '</strong>' . EOL;
+                               $checked .= " disabled ";
+                       }
+                       else {
+                               $o .= EOL . '<strong>' . t('Facebook friend linking has been disabled on this site. If you disable it, you will be unable to re-enable it.') . '</strong>' . EOL;
+                       }
+               }
                $o .= '<input type="checkbox" name="facebook_linking" value="1"' . $checked . '/>' . ' ' . t('Link all your Facebook friends and conversations on this website') . EOL ;
 
                $o .= '<p>' . t('Facebook conversations consist of your <em>profile wall</em> and your friend <em>stream</em>.');
@@ -556,7 +601,11 @@ function facebook_content(&$a) {
 }
 
 
-
+/**
+ * @param App $a
+ * @param null|object $b
+ * @return mixed
+ */
 function facebook_cron($a,$b) {
 
        $last = get_config('facebook','last_poll');
@@ -566,7 +615,7 @@ function facebook_cron($a,$b) {
                $poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL;
 
        if($last) {
-               $next = $last + $poll_interval;
+               $next = $last + ($poll_interval * 60);
                if($next > time()) 
                        return;
        }
@@ -597,6 +646,8 @@ function facebook_cron($a,$b) {
                        $last_friend_check = get_pconfig($rr['uid'],'facebook','friend_check');
                        if($last_friend_check) 
                                $next_friend_check = $last_friend_check + 86400;
+                       else
+                           $next_friend_check = 0;
                        if($next_friend_check <= time()) {
                                fb_get_friends($rr['uid'], true);
                                set_pconfig($rr['uid'],'facebook','friend_check',time());
@@ -615,9 +666,16 @@ function facebook_cron($a,$b) {
                                logger('facebook_cron: Successful', LOGGER_NORMAL);
                        else {
                                logger('facebook_cron: Failed', LOGGER_NORMAL);
-                               
-                               if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent')) {
-                                       $res = mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'), 
+
+                               $first_err = get_config('facebook', 'realtime_first_err');
+                               if (!$first_err) {
+                                       $first_err = time();
+                                       set_config('facebook', 'realtime_first_err', $first_err);
+                               }
+                               $first_err_ago = (time() - $first_err);
+
+                               if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent') && $first_err_ago > (FACEBOOK_RTU_ERR_MAIL_AFTER_MINUTES * 60)) {
+                                       mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'),
                                                "Hi!\n\nThere's a problem with the Facebook Real-Time Updates that cannot be solved automatically. Maybe a permission issue?\n\nPlease try to re-activate it on " . $a->config["system"]["url"] . "/admin/plugins/facebook\n\nThis e-mail will only be sent once.",
                                                'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n"
                                                . 'Content-type: text/plain; charset=UTF-8' . "\n"
@@ -629,6 +687,7 @@ function facebook_cron($a,$b) {
                        }
                } else { // !facebook_check_realtime_active()
                        del_config('facebook', 'realtime_err_mailsent');
+                       del_config('facebook', 'realtime_first_err');
                }
        }
        
@@ -637,7 +696,10 @@ function facebook_cron($a,$b) {
 }
 
 
-
+/**
+ * @param App $a
+ * @param null|object $b
+ */
 function facebook_plugin_settings(&$a,&$b) {
 
        $b .= '<div class="settings-block">';
@@ -648,6 +710,10 @@ function facebook_plugin_settings(&$a,&$b) {
 }
 
 
+/**
+ * @param App $a
+ * @param null|object $o
+ */
 function facebook_plugin_admin(&$a, &$o){
 
 
@@ -658,6 +724,7 @@ function facebook_plugin_admin(&$a, &$o){
        $appid  = get_config('facebook', 'appid'  );
        $appsecret = get_config('facebook', 'appsecret' );
        $poll_interval = get_config('facebook', 'poll_interval' );
+       $sync_comments = get_config('facebook', 'sync_comments' );
        if (!$poll_interval) $poll_interval = FACEBOOK_DEFAULT_POLL_INTERVAL;
        
        $ret1 = q("SELECT `v` FROM `config` WHERE `cat` = 'facebook' AND `k` = 'appid' LIMIT 1");
@@ -674,9 +741,10 @@ function facebook_plugin_admin(&$a, &$o){
                } else $o .= t('The correctness of the API Key could not be detected. Somthing strange\'s going on.') . '<br>';
        }
        
-       $o .= '<label for="fb_appid">' . t('App-ID / API-Key') . '</label><input name="appid" type="text" value="' . escape_tags($appid ? $appid : "") . '"><br style="clear: both;">';
-       $o .= '<label for="fb_appsecret">' . t('Application secret') . '</label><input name="appsecret" type="text" value="' . escape_tags($appsecret ? $appsecret : "") . '"><br style="clear: both;">';
-       $o .= '<label for="fb_poll_interval">' . sprintf(t('Polling Interval (min. %1$s minutes)'), FACEBOOK_MIN_POLL_INTERVAL) . '</label><input name="poll_interval" type="number" min="' . FACEBOOK_MIN_POLL_INTERVAL . '" value="' . $poll_interval . '"><br style="clear: both;">';
+       $o .= '<label for="fb_appid">' . t('App-ID / API-Key') . '</label><input id="fb_appid" name="appid" type="text" value="' . escape_tags($appid ? $appid : "") . '"><br style="clear: both;">';
+       $o .= '<label for="fb_appsecret">' . t('Application secret') . '</label><input id="fb_appsecret" name="appsecret" type="text" value="' . escape_tags($appsecret ? $appsecret : "") . '"><br style="clear: both;">';
+       $o .= '<label for="fb_poll_interval">' . sprintf(t('Polling Interval in minutes (minimum %1$s minutes)'), FACEBOOK_MIN_POLL_INTERVAL) . '</label><input name="poll_interval" id="fb_poll_interval" type="number" min="' . FACEBOOK_MIN_POLL_INTERVAL . '" value="' . $poll_interval . '"><br style="clear: both;">';
+       $o .= '<label for="fb_sync_comments">' . t('Synchronize comments (no comments on Facebook are missed, at the cost of increased system load)') . '</label><input name="sync_comments" id="fb_sync_comments" type="checkbox" ' . ($sync_comments ? 'checked' : '') . '><br style="clear: both;">';
        $o .= '<input type="submit" name="fb_save_keys" value="' . t('Save') . '">';
        
        if ($working_connection) {
@@ -692,7 +760,11 @@ function facebook_plugin_admin(&$a, &$o){
        }
 }
 
-function facebook_plugin_admin_post(&$a, &$o){
+/**
+ * @param App $a
+ */
+
+function facebook_plugin_admin_post(&$a){
        check_form_security_token_redirectOnErr('/admin/plugins/facebook', 'fbsave');
        
        if (x($_REQUEST,'fb_save_keys')) {
@@ -700,6 +772,7 @@ function facebook_plugin_admin_post(&$a, &$o){
                set_config('facebook', 'appsecret', $_REQUEST['appsecret']);
                $poll_interval = IntVal($_REQUEST['poll_interval']);
                if ($poll_interval >= FACEBOOK_MIN_POLL_INTERVAL) set_config('facebook', 'poll_interval', $poll_interval);
+               set_config('facebook', 'sync_comments', (x($_REQUEST, 'sync_comments') ? 1 : 0));
                del_config('facebook', 'app_access_token');
                info(t('The new values have been saved.'));
        }
@@ -711,6 +784,11 @@ function facebook_plugin_admin_post(&$a, &$o){
        }
 }
 
+/**
+ * @param App $a
+ * @param object $b
+ * @return mixed
+ */
 function facebook_jot_nets(&$a,&$b) {
        if(! local_user())
                return;
@@ -725,6 +803,11 @@ function facebook_jot_nets(&$a,&$b) {
 }
 
 
+/**
+ * @param App $a
+ * @param object $b
+ * @return mixed
+ */
 function facebook_post_hook(&$a,&$b) {
 
 
@@ -743,6 +826,9 @@ function facebook_post_hook(&$a,&$b) {
        $reply = false;
        $likes = false;
 
+       $deny_arr = array();
+       $allow_arr = array();
+
        $toplevel = (($b['id'] == $b['parent']) ? true : false);
 
 
@@ -789,8 +875,7 @@ function facebook_post_hook(&$a,&$b) {
                        $allow_str = dbesc(implode(', ',$recipients));
                        if($allow_str) {
                                $r = q("SELECT `notify` FROM `contact` WHERE `id` IN ( $allow_str ) AND `network` = 'face'"); 
-                               $allow_arr = array();
-                               if(count($r)) 
+                               if(count($r))
                                        foreach($r as $rr)
                                                $allow_arr[] = $rr['notify'];
                        }
@@ -798,8 +883,7 @@ function facebook_post_hook(&$a,&$b) {
                        $deny_str = dbesc(implode(', ',$deny));
                        if($deny_str) {
                                $r = q("SELECT `notify` FROM `contact` WHERE `id` IN ( $deny_str ) AND `network` = 'face'"); 
-                               $deny_arr = array();
-                               if(count($r)) 
+                               if(count($r))
                                        foreach($r as $rr)
                                                $deny_arr[] = $rr['notify'];
                        }
@@ -854,8 +938,8 @@ function facebook_post_hook(&$a,&$b) {
 
                                // unless it's a dislike - just send the text as a comment
 
-                               if($b['verb'] == ACTIVITY_DISLIKE)
-                                       $msg = trim(strip_tags(bbcode($msg)));
+                               // if($b['verb'] == ACTIVITY_DISLIKE)
+                               //      $msg = trim(strip_tags(bbcode($msg)));
 
                                // Old code
                                /*$search_str = $a->get_baseurl() . '/search';
@@ -896,7 +980,7 @@ function facebook_post_hook(&$a,&$b) {
                                if(preg_match("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/is",$b['body'],$matches))
                                        $image = $matches[3];
 
-                               if ($image != '')
+                               if ($image == '')
                                        if(preg_match("/\[img\](.*?)\[\/img\]/is",$b['body'],$matches))
                                                $image = $matches[1];
 
@@ -965,7 +1049,6 @@ function facebook_post_hook(&$a,&$b) {
 
                                // Since facebook increased the maxpostlen massively this never should happen again :)
                                if (strlen($msg) > FACEBOOK_MAXPOSTLEN) {
-                                       $shortlink = "";
                                        require_once('library/slinky.php');
 
                                        $display_url = $b['plink'];
@@ -1006,10 +1089,14 @@ function facebook_post_hook(&$a,&$b) {
                                                'access_token' => $fb_token, 
                                                'message' => $msg
                                        );
-                                       if(isset($image))
+                                       if(isset($image)) {
                                                $postvars['picture'] = $image;
-                                       if(isset($link))
+                                               //$postvars['type'] = "photo";
+                                       }
+                                       if(isset($link)) {
                                                $postvars['link'] = $link;
+                                               //$postvars['type'] = "link";
+                                       }
                                        if(isset($linkname))
                                                $postvars['name'] = $linkname;
                                }
@@ -1026,11 +1113,18 @@ function facebook_post_hook(&$a,&$b) {
 
                                if($reply) {
                                        $url = 'https://graph.facebook.com/' . $reply . '/' . (($likes) ? 'likes' : 'comments');
-                               }
-                               else { 
+                               } else if (($link != "")  or ($image != "") or ($b['title'] == '') or (strlen($msg) < 500)) { 
                                        $url = 'https://graph.facebook.com/me/feed';
                                        if($b['plink'])
                                                $postvars['actions'] = '{"name": "' . t('View on Friendica') . '", "link": "' .  $b['plink'] . '"}';
+                               } else {
+                                       // if its only a message and a subject and the message is larger than 500 characters then post it as note
+                                       $postvars = array(
+                                               'access_token' => $fb_token, 
+                                               'message' => bbcode($b['body']),
+                                               'subject' => $b['title'],
+                                       );
+                                       $url = 'https://graph.facebook.com/me/notes';
                                }
 
                                logger('facebook: post to ' . $url);
@@ -1088,6 +1182,10 @@ function facebook_post_hook(&$a,&$b) {
        }
 }
 
+/**
+ * @param App $app
+ * @param object $data
+ */
 function facebook_enotify(&$app, &$data) {
        if (x($data, 'params') && $data['params']['type'] == NOTIFY_SYSTEM && x($data['params'], 'system_type') && $data['params']['system_type'] == 'facebook_connection_invalid') {
                $data['itemlink'] = '/facebook';
@@ -1097,6 +1195,10 @@ function facebook_enotify(&$app, &$data) {
        }
 }
 
+/**
+ * @param App $a
+ * @param object $b
+ */
 function facebook_post_local(&$a,&$b) {
 
        // Figure out if Facebook posting is enabled for this post and file it in 'postopts'
@@ -1123,6 +1225,10 @@ function facebook_post_local(&$a,&$b) {
 }
 
 
+/**
+ * @param App $a
+ * @param object $b
+ */
 function fb_queue_hook(&$a,&$b) {
 
        $qi = q("SELECT * FROM `queue` WHERE `network` = '%s'",
@@ -1181,8 +1287,14 @@ function fb_queue_hook(&$a,&$b) {
        }
 }
 
+/**
+ * @param string $access_token
+ * @param int $since
+ * @return object
+ */
 function fb_get_timeline($access_token, &$since) {
 
+    $entries = new stdClass();
        $entries->data = array();
        $newest = 0;
 
@@ -1211,7 +1323,7 @@ function fb_get_timeline($access_token, &$since) {
                else
                        break;
 
-               $url = $j->paging->next;
+               $url = (isset($j->paging) && isset($j->paging->next) ? $j->paging->next : '');
 
        } while (($oldestdate > $since) and ($since != 0) and ($url != ''));
 
@@ -1221,6 +1333,9 @@ function fb_get_timeline($access_token, &$since) {
        return($entries);
 }
 
+/**
+ * @param int $uid
+ */
 function fb_consume_all($uid) {
 
        require_once('include/items.php');
@@ -1245,7 +1360,7 @@ function fb_consume_all($uid) {
        // Get the last date
        $lastdate = get_pconfig($uid,'facebook','lastdate');
        // fetch all items since the last date
-       $j = fb_get_timeline($access_token, &$lastdate);
+       $j = fb_get_timeline($access_token, $lastdate);
        if (isset($j->data)) {
                logger('fb_consume_stream: feed: ' . print_r($j,true), LOGGER_DATA);
                fb_consume_stream($uid,$j,false);
@@ -1256,6 +1371,11 @@ function fb_consume_all($uid) {
                logger('fb_consume_stream: feed: got no data from Facebook: ' . print_r($j,true), LOGGER_NORMAL);
 }
 
+/**
+ * @param int $uid
+ * @param string $link
+ * @return string
+ */
 function fb_get_photo($uid,$link) {
        $access_token = get_pconfig($uid,'facebook','access_token');
        if(! $access_token || (! stristr($link,'facebook.com/photo.php')))
@@ -1264,26 +1384,246 @@ function fb_get_photo($uid,$link) {
        $ret = preg_match('/fbid=([0-9]*)/',$link,$match);
        if($ret)
                $photo_id = $match[1];
+       else
+           return "";
        $x = fetch_url('https://graph.facebook.com/' . $photo_id . '?access_token=' . $access_token);
        $j = json_decode($x);
        if($j->picture)
                return "\n\n" . '[url=' . $link . '][img]' . $j->picture . '[/img][/url]';
        //else
        //      return "\n" . '[url=' . $link . ']' . t('link') . '[/url]';
+       return "";
+}
+
+
+/**
+ * @param App $a
+ * @param array $user
+ * @param array $self
+ * @param string $fb_id
+ * @param bool $wall
+ * @param array $orig_post
+ * @param object $cmnt
+ */
+function fb_consume_comment(&$a, &$user, &$self, $fb_id, $wall, &$orig_post, &$cmnt) {
+
+    if(! $orig_post)
+        return;
+
+    $top_item = $orig_post['id'];
+    $uid = IntVal($user[0]['uid']);
+
+    $r = q("SELECT * FROM `item` WHERE `uid` = %d AND ( `uri` = '%s' OR `extid` = '%s' ) LIMIT 1",
+        intval($uid),
+        dbesc('fb::' . $cmnt->id),
+        dbesc('fb::' . $cmnt->id)
+    );
+    if(count($r))
+        return;
+
+    $cmntdata = array();
+    $cmntdata['parent'] = $top_item;
+    $cmntdata['verb'] = ACTIVITY_POST;
+    $cmntdata['gravity'] = 6;
+    $cmntdata['uid'] = $uid;
+    $cmntdata['wall'] = (($wall) ? 1 : 0);
+    $cmntdata['uri'] = 'fb::' . $cmnt->id;
+    $cmntdata['parent-uri'] = $orig_post['uri'];
+    if($cmnt->from->id == $fb_id) {
+        $cmntdata['contact-id'] = $self[0]['id'];
+    }
+    else {
+        $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d LIMIT 1",
+            dbesc($cmnt->from->id),
+            intval($uid)
+        );
+        if(count($r)) {
+            $cmntdata['contact-id'] = $r[0]['id'];
+            if($r[0]['blocked'] || $r[0]['readonly'])
+                return;
+        }
+    }
+    if(! x($cmntdata,'contact-id'))
+        $cmntdata['contact-id'] = $orig_post['contact-id'];
+
+    $cmntdata['app'] = 'facebook';
+    $cmntdata['created'] = datetime_convert('UTC','UTC',$cmnt->created_time);
+    $cmntdata['edited']  = datetime_convert('UTC','UTC',$cmnt->created_time);
+    $cmntdata['verb'] = ACTIVITY_POST;
+    $cmntdata['author-name'] = $cmnt->from->name;
+    $cmntdata['author-link'] = 'http://facebook.com/profile.php?id=' . $cmnt->from->id;
+    $cmntdata['author-avatar'] = 'https://graph.facebook.com/' . $cmnt->from->id . '/picture';
+    $cmntdata['body'] = $cmnt->message;
+    $item = item_store($cmntdata);
+
+    $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 AND `deleted` = 0",
+        dbesc($orig_post['uri']),
+        intval($uid)
+    );
+
+    if(count($myconv)) {
+        $importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
+
+        foreach($myconv as $conv) {
+
+            // now if we find a match, it means we're in this conversation
+
+            if(! link_compare($conv['author-link'],$importer_url))
+                continue;
+
+            require_once('include/enotify.php');
+
+            $conv_parent = $conv['parent'];
+
+            notification(array(
+                'type'         => NOTIFY_COMMENT,
+                'notify_flags' => $user[0]['notify-flags'],
+                'language'     => $user[0]['language'],
+                'to_name'      => $user[0]['username'],
+                'to_email'     => $user[0]['email'],
+                'uid'          => $user[0]['uid'],
+                'item'         => $cmntdata,
+                'link'            => $a->get_baseurl() . '/display/' . $user[0]['nickname'] . '/' . $item,
+                'source_name'  => $cmntdata['author-name'],
+                'source_link'  => $cmntdata['author-link'],
+                'source_photo' => $cmntdata['author-avatar'],
+                'verb'         => ACTIVITY_POST,
+                'otype'        => 'item',
+                'parent'       => $conv_parent,
+            ));
+
+            // only send one notification
+            break;
+        }
+    }
+}
+
+
+/**
+ * @param App $a
+ * @param array $user
+ * @param array $self
+ * @param string $fb_id
+ * @param bool $wall
+ * @param array $orig_post
+ * @param object $likes
+ */
+function fb_consume_like(&$a, &$user, &$self, $fb_id, $wall, &$orig_post, &$likes) {
+
+    $top_item = $orig_post['id'];
+    $uid = IntVal($user[0]['uid']);
+
+    if(! $orig_post)
+        return;
+
+    // If we posted the like locally, it will be found with our url, not the FB url.
+
+    $second_url = (($likes->id == $fb_id) ? $self[0]['url'] : 'http://facebook.com/profile.php?id=' . $likes->id);
+
+    $r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s'
+       AND ( `author-link` = '%s' OR `author-link` = '%s' ) LIMIT 1",
+        dbesc($orig_post['uri']),
+        intval($uid),
+        dbesc(ACTIVITY_LIKE),
+        dbesc('http://facebook.com/profile.php?id=' . $likes->id),
+        dbesc($second_url)
+    );
+
+    if(count($r))
+        return;
+
+    $likedata = array();
+    $likedata['parent'] = $top_item;
+    $likedata['verb'] = ACTIVITY_LIKE;
+    $likedata['gravity'] = 3;
+    $likedata['uid'] = $uid;
+    $likedata['wall'] = (($wall) ? 1 : 0);
+    $likedata['uri'] = item_new_uri($a->get_baseurl(), $uid);
+    $likedata['parent-uri'] = $orig_post['uri'];
+    if($likes->id == $fb_id)
+        $likedata['contact-id'] = $self[0]['id'];
+    else {
+        $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
+            dbesc($likes->id),
+            intval($uid)
+        );
+        if(count($r))
+            $likedata['contact-id'] = $r[0]['id'];
+    }
+    if(! x($likedata,'contact-id'))
+        $likedata['contact-id'] = $orig_post['contact-id'];
+
+    $likedata['app'] = 'facebook';
+    $likedata['verb'] = ACTIVITY_LIKE;
+    $likedata['author-name'] = $likes->name;
+    $likedata['author-link'] = 'http://facebook.com/profile.php?id=' . $likes->id;
+    $likedata['author-avatar'] = 'https://graph.facebook.com/' . $likes->id . '/picture';
+
+    $author  = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]';
+    $objauthor =  '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]';
+    $post_type = t('status');
+    $plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]';
+    $likedata['object-type'] = ACTIVITY_OBJ_NOTE;
+
+    $likedata['body'] = sprintf( t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink);
+    $likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' .
+        '<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>';
+
+    item_store($likedata);
+}
+
+/**
+ * @param App $a
+ * @param array $user
+ * @param object $entry
+ * @param array $self
+ * @param string $fb_id
+ * @param bool $wall
+ * @param array $orig_post
+ */
+function fb_consume_status(&$a, &$user, &$entry, &$self, $fb_id, $wall, &$orig_post) {
+    $uid = IntVal($user[0]['uid']);
+    $access_token = get_pconfig($uid, 'facebook', 'access_token');
+
+    $s = fetch_url('https://graph.facebook.com/' . $entry->id . '?access_token=' . $access_token);
+    if($s) {
+        $j = json_decode($s);
+        if (isset($j->comments) && isset($j->comments->data))
+            foreach ($j->comments->data as $cmnt)
+                fb_consume_comment($a, $user, $self, $fb_id, $wall, $orig_post, $cmnt);
+
+        if (isset($j->likes) && isset($j->likes->data) && isset($j->likes->count)) {
+            if (count($j->likes->data) == $j->likes->count) {
+                foreach ($j->likes->data as $likers) fb_consume_like($a, $user, $self, $fb_id, $wall, $orig_post, $likers);
+            } else {
+                $t = fetch_url('https://graph.facebook.com/' . $entry->id . '/likes?access_token=' . $access_token);
+                if ($t) {
+                    $k = json_decode($t);
+                    if (isset($k->data))
+                        foreach ($k->data as $likers)
+                            fb_consume_like($a, $user, $self, $fb_id, $wall, $orig_post, $likers);
+                }
+            }
+        }
+    }
 }
 
+/**
+ * @param int $uid
+ * @param object $j
+ * @param bool $wall
+ */
 function fb_consume_stream($uid,$j,$wall = false) {
 
        $a = get_app();
 
-
        $user = q("SELECT * FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
                intval($uid)
        );
        if(! count($user))
                return;
 
-       $my_local_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
+       // $my_local_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
 
        $no_linking = get_pconfig($uid,'facebook','no_linking');
        if($no_linking)
@@ -1296,11 +1636,16 @@ function fb_consume_stream($uid,$j,$wall = false) {
        $blocked_apps = get_pconfig($uid,'facebook','blocked_apps');
        $blocked_apps_arr = explode(',',$blocked_apps);
 
+       $sync_comments = get_config('facebook', 'sync_comments');
+
+    /** @var string $self_id  */
        $self_id = get_pconfig($uid,'facebook','self_id');
        if(! count($j->data) || (! strlen($self_id)))
                return;
 
-       foreach($j->data as $entry) {
+    $top_item = 0;
+
+    foreach($j->data as $entry) {
                logger('fb_consume: entry: ' . print_r($entry,true), LOGGER_DATA);
                $datarray = array();
 
@@ -1310,12 +1655,10 @@ function fb_consume_stream($uid,$j,$wall = false) {
                                intval($uid)
                );
                if(count($r)) {
-                       $post_exists = true;
                        $orig_post = $r[0];
                        $top_item = $r[0]['id'];
                }
                else {
-                       $post_exists = false;
                        $orig_post = null;
                }
 
@@ -1330,7 +1673,7 @@ function fb_consume_stream($uid,$j,$wall = false) {
                        else {
                                // Looking if user is known - if not he is added
                                $access_token = get_pconfig($uid, 'facebook', 'access_token');
-                               fb_get_friends_sync_new($uid, $access_token, $from);
+                               fb_get_friends_sync_new($uid, $access_token, array($from));
 
                                $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
                                        dbesc($from->id),
@@ -1379,32 +1722,32 @@ function fb_consume_stream($uid,$j,$wall = false) {
 
                        logger('facebook: post '.$entry->id.' from '.$from->name);
 
-                       $datarray['body'] = escape_tags($entry->message);
+                       $datarray['body'] = (isset($entry->message) ? escape_tags($entry->message) : '');
 
-                       if($entry->name and $entry->link)
+                       if(isset($entry->name) and isset($entry->link))
                                $datarray['body'] .= "\n\n[bookmark=".$entry->link."]".$entry->name."[/bookmark]";
-                       elseif ($entry->name)
+                       elseif (isset($entry->name))
                                $datarray['body'] .= "\n\n[b]" . $entry->name."[/b]";
 
-                       if($entry->caption) {
-                               if(!$entry->name and $entry->link)
+                       if(isset($entry->caption)) {
+                               if(!isset($entry->name) and isset($entry->link))
                                        $datarray['body'] .= "\n\n[bookmark=".$entry->link."]".$entry->caption."[/bookmark]";
                                else
                                        $datarray['body'] .= "[i]" . $entry->caption."[/i]\n";
                        }
 
-                       if(!$entry->caption and !$entry->name) {
-                               if ($entry->link)
+                       if(!isset($entry->caption) and !isset($entry->name)) {
+                               if (isset($entry->link))
                                        $datarray['body'] .= "\n[url]".$entry->link."[/url]\n";
                                else
                                        $datarray['body'] .= "\n";
                        }
 
                        $quote = "";
-                       if($entry->description)
+                       if(isset($entry->description))
                                $quote = $entry->description;
 
-                       if ($entry->properties)
+                       if (isset($entry->properties))
                                foreach ($entry->properties as $property)
                                        $quote .= "\n".$property->name.": [url=".$property->href."]".$property->text."[/url]";
 
@@ -1414,22 +1757,31 @@ function fb_consume_stream($uid,$j,$wall = false) {
                        // Only import the picture when the message is no video
                        // oembed display a picture of the video as well 
                        if ($entry->type != "video") {
-                               if($entry->picture && $entry->link) {
+                               if(isset($entry->picture) && isset($entry->link)) {
                                        $datarray['body'] .= "\n" . '[url=' . $entry->link . '][img]'.$entry->picture.'[/img][/url]';   
                                }
                                else {
-                                       if($entry->picture)
+                                       if(isset($entry->picture))
                                                $datarray['body'] .= "\n" . '[img]' . $entry->picture . '[/img]';
                                        // if just a link, it may be a wall photo - check
-                                       if($entry->link)
+                                       if(isset($entry->link))
                                                $datarray['body'] .= fb_get_photo($uid,$entry->link);
                                }
                        }
 
+                       if (($datarray['app'] == "Events") and isset($entry->actions))
+                               foreach ($entry->actions as $action)
+                                       if ($action->name == "View")
+                                               $datarray['body'] .= " [url=".$action->link."]".$entry->story."[/url]";
+
                        // Just as a test - to see if these are the missing entries
                        //if(trim($datarray['body']) == '')
                        //      $datarray['body'] = $entry->story;
 
+                       // Adding the "story" text to see if there are useful data in it (testing)
+                       //if (($datarray['app'] != "Events") and $entry->story)
+                       //      $datarray['body'] .= "\n".$entry->story;
+
                        if(trim($datarray['body']) == '') {
                                logger('facebook: empty body '.$entry->id.' '.print_r($entry, true));
                                continue;
@@ -1437,10 +1789,10 @@ function fb_consume_stream($uid,$j,$wall = false) {
 
                        $datarray['body'] .= "\n";
 
-                       if ($entry->icon)
+                       if (isset($entry->icon))
                                $datarray['body'] .= "[img]".$entry->icon."[/img] &nbsp; ";
 
-                       if ($entry->actions)
+                       if (isset($entry->actions))
                                foreach ($entry->actions as $action)
                                        if (($action->name != "Comment") and ($action->name != "Like"))
                                                $datarray['body'] .= "[url=".$action->link."]".$action->name."[/url] &nbsp; ";
@@ -1450,26 +1802,29 @@ function fb_consume_stream($uid,$j,$wall = false) {
                        //if(($datarray['body'] != '') and ($uid == 1))
                        //      $datarray['body'] .= "[noparse]".print_r($entry, true)."[/noparse]";
 
-                       if ($entry->place->name)
-                               $datarray['coord'] = $entry->place->name;
-                       else if ($entry->place->location->street or $entry->place->location->city or $entry->place->location->Denmark) {
-                               if ($entry->place->location->street)
-                                       $datarray['coord'] = $entry->place->location->street;
-                               if ($entry->place->location->city)
-                                       $datarray['coord'] .= " ".$entry->place->location->city;
-                               if ($entry->place->location->country)
-                                       $datarray['coord'] .= " ".$entry->place->location->country;
-                       } else if ($entry->place->location->latitude and $entry->place->location->longitude)
-                               $datarray['coord'] = substr($entry->place->location->latitude, 0, 8)
+            if (isset($entry->place)) {
+                           if ($entry->place->name or $entry->place->location->street or
+                                   $entry->place->location->city or $entry->place->location->Denmark) {
+                                   $datarray['coord'] = '';
+                                   if ($entry->place->name)
+                                           $datarray['coord'] .= $entry->place->name;
+                                   if ($entry->place->location->street)
+                                           $datarray['coord'] .= $entry->place->location->street;
+                                   if ($entry->place->location->city)
+                                           $datarray['coord'] .= " ".$entry->place->location->city;
+                                   if ($entry->place->location->country)
+                                           $datarray['coord'] .= " ".$entry->place->location->country;
+                           } else if ($entry->place->location->latitude and $entry->place->location->longitude)
+                                   $datarray['coord'] = substr($entry->place->location->latitude, 0, 8)
                                                        .' '.substr($entry->place->location->longitude, 0, 8);
-
+            }
                        $datarray['created'] = datetime_convert('UTC','UTC',$entry->created_time);
                        $datarray['edited'] = datetime_convert('UTC','UTC',$entry->updated_time);
 
                        // If the entry has a privacy policy, we cannot assume who can or cannot see it,
                        // as the identities are from a foreign system. Mark it as private to the owner.
 
-                       if($entry->privacy && $entry->privacy->value !== 'EVERYONE') {
+                       if(isset($entry->privacy) && $entry->privacy->value !== 'EVERYONE') {
                                $datarray['private'] = 1;
                                $datarray['allow_cid'] = '<' . $self[0]['id'] . '>';
                        }
@@ -1485,173 +1840,60 @@ function fb_consume_stream($uid,$j,$wall = false) {
                        }
                }
 
+               /**  @var array $orig_post */
+
+        $likers_num = (isset($entry->likes) && isset($entry->likes->count) ? IntVal($entry->likes->count) : 0 );
                if(isset($entry->likes) && isset($entry->likes->data))
                        $likers = $entry->likes->data;
                else
                        $likers = null;
 
+        $comments_num = (isset($entry->comments) && isset($entry->comments->count) ? IntVal($entry->comments->count) : 0 );
                if(isset($entry->comments) && isset($entry->comments->data))
                        $comments = $entry->comments->data;
                else
                        $comments = null;
 
-               if(is_array($likers)) {
-                       foreach($likers as $likes) {
-
-                               if(! $orig_post)
-                                       continue;
-
-                               // If we posted the like locally, it will be found with our url, not the FB url.
-
-                               $second_url = (($likes->id == $self_id) ? $self[0]['url'] : 'http://facebook.com/profile.php?id=' . $likes->id); 
-
-                               $r = q("SELECT * FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' 
-                                       AND ( `author-link` = '%s' OR `author-link` = '%s' ) LIMIT 1",
-                                       dbesc($orig_post['uri']),
-                                       intval($uid),
-                                       dbesc(ACTIVITY_LIKE),
-                                       dbesc('http://facebook.com/profile.php?id=' . $likes->id),
-                                       dbesc($second_url)
-                               );
-
-                               if(count($r))
-                                       continue;
-                                       
-                               $likedata = array();
-                               $likedata['parent'] = $top_item;
-                               $likedata['verb'] = ACTIVITY_LIKE;
-                               $likedata['gravity'] = 3;
-                               $likedata['uid'] = $uid;
-                               $likedata['wall'] = (($wall) ? 1 : 0);
-                               $likedata['uri'] = item_new_uri($a->get_baseurl(), $uid);
-                               $likedata['parent-uri'] = $orig_post['uri'];
-                               if($likes->id == $self_id)
-                                       $likedata['contact-id'] = $self[0]['id'];
-                               else {
-                                       $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
-                                               dbesc($likes->id),
-                                               intval($uid)
-                                       );
-                                       if(count($r))
-                                               $likedata['contact-id'] = $r[0]['id'];
-                               }
-                               if(! x($likedata,'contact-id'))
-                                       $likedata['contact-id'] = $orig_post['contact-id'];
-
-                               $likedata['app'] = 'facebook';
-                               $likedata['verb'] = ACTIVITY_LIKE;                                              
-                               $likedata['author-name'] = $likes->name;
-                               $likedata['author-link'] = 'http://facebook.com/profile.php?id=' . $likes->id;
-                               $likedata['author-avatar'] = 'https://graph.facebook.com/' . $likes->id . '/picture';
-                               
-                               $author  = '[url=' . $likedata['author-link'] . ']' . $likedata['author-name'] . '[/url]';
-                               $objauthor =  '[url=' . $orig_post['author-link'] . ']' . $orig_post['author-name'] . '[/url]';
-                               $post_type = t('status');
-                       $plink = '[url=' . $orig_post['plink'] . ']' . $post_type . '[/url]';
-                               $likedata['object-type'] = ACTIVITY_OBJ_NOTE;
-
-                               $likedata['body'] = sprintf( t('%1$s likes %2$s\'s %3$s'), $author, $objauthor, $plink);
-                               $likedata['object'] = '<object><type>' . ACTIVITY_OBJ_NOTE . '</type><local>1</local>' . 
-                                       '<id>' . $orig_post['uri'] . '</id><link>' . xmlify('<link rel="alternate" type="text/html" href="' . xmlify($orig_post['plink']) . '" />') . '</link><title>' . $orig_post['title'] . '</title><content>' . $orig_post['body'] . '</content></object>';  
-
-                               $item = item_store($likedata);                  
-                       }
+        $needs_sync = false;
+
+        if(is_array($likers)) {
+                       foreach($likers as $likes) fb_consume_like($a, $user, $self, $self_id, $wall, $orig_post, $likes);
+            if ($sync_comments) {
+                $r = q("SELECT COUNT(*) likes FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' AND `parent-uri` != `uri`",
+                    dbesc($orig_post['uri']),
+                    intval($uid),
+                    dbesc(ACTIVITY_LIKE)
+                );
+                if ($r[0]['likes'] < $likers_num) {
+                    logger('fb_consume_stream: missing likes found for ' . $orig_post['uri'] . ' (we have ' . $r[0]['likes'] . ' of ' . $likers_num . '). Synchronizing...', LOGGER_DEBUG);
+                    $needs_sync = true;
+                }
+            }
                }
-               if(is_array($comments)) {
-                       foreach($comments as $cmnt) {
-
-                               if(! $orig_post)
-                                       continue;
-
-                               $r = q("SELECT * FROM `item` WHERE `uid` = %d AND ( `uri` = '%s' OR `extid` = '%s' ) LIMIT 1",
-                                       intval($uid),
-                                       dbesc('fb::' . $cmnt->id),
-                                       dbesc('fb::' . $cmnt->id)
-                               );
-                               if(count($r))
-                                       continue;
 
-                               $cmntdata = array();
-                               $cmntdata['parent'] = $top_item;
-                               $cmntdata['verb'] = ACTIVITY_POST;
-                               $cmntdata['gravity'] = 6;
-                               $cmntdata['uid'] = $uid;
-                               $cmntdata['wall'] = (($wall) ? 1 : 0);
-                               $cmntdata['uri'] = 'fb::' . $cmnt->id;
-                               $cmntdata['parent-uri'] = $orig_post['uri'];
-                               if($cmnt->from->id == $self_id) {
-                                       $cmntdata['contact-id'] = $self[0]['id'];
-                               }
-                               else {
-                                       $r = q("SELECT * FROM `contact` WHERE `notify` = '%s' AND `uid` = %d LIMIT 1",
-                                               dbesc($cmnt->from->id),
-                                               intval($uid)
-                                       );
-                                       if(count($r)) {
-                                               $cmntdata['contact-id'] = $r[0]['id'];
-                                               if($r[0]['blocked'] || $r[0]['readonly'])
-                                                       continue;
-                                       }
-                               }
-                               if(! x($cmntdata,'contact-id'))
-                                       $cmntdata['contact-id'] = $orig_post['contact-id'];
-
-                               $cmntdata['app'] = 'facebook';
-                               $cmntdata['created'] = datetime_convert('UTC','UTC',$cmnt->created_time);
-                               $cmntdata['edited']  = datetime_convert('UTC','UTC',$cmnt->created_time);
-                               $cmntdata['verb'] = ACTIVITY_POST;                                              
-                               $cmntdata['author-name'] = $cmnt->from->name;
-                               $cmntdata['author-link'] = 'http://facebook.com/profile.php?id=' . $cmnt->from->id;
-                               $cmntdata['author-avatar'] = 'https://graph.facebook.com/' . $cmnt->from->id . '/picture';
-                               $cmntdata['body'] = $cmnt->message;
-                               $item = item_store($cmntdata);                  
-                               
-                               $myconv = q("SELECT `author-link`, `author-avatar`, `parent` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `parent` != 0 ",
-                                       dbesc($orig_post['uri']),
-                                       intval($uid)
-                               );
-
-                               if(count($myconv)) {
-                                       $importer_url = $a->get_baseurl() . '/profile/' . $user[0]['nickname'];
-
-                                       foreach($myconv as $conv) {
-
-                                               // now if we find a match, it means we're in this conversation
-       
-                                               if(! link_compare($conv['author-link'],$importer_url))
-                                                       continue;
-
-                                               require_once('include/enotify.php');
-                                                               
-                                               $conv_parent = $conv['parent'];
-
-                                               notification(array(
-                                                       'type'         => NOTIFY_COMMENT,
-                                                       'notify_flags' => $user[0]['notify-flags'],
-                                                       'language'     => $user[0]['language'],
-                                                       'to_name'      => $user[0]['username'],
-                                                       'to_email'     => $user[0]['email'],
-                                                       'uid'          => $user[0]['uid'],
-                                                       'item'         => $cmntdata,
-                                                       'link'             => $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $item,
-                                                       'source_name'  => $cmntdata['author-name'],
-                                                       'source_link'  => $cmntdata['author-link'],
-                                                       'source_photo' => $cmntdata['author-avatar'],
-                                                       'verb'         => ACTIVITY_POST,
-                                                       'otype'        => 'item',
-                                                       'parent'       => $conv_parent,
-                                               ));
-
-                                               // only send one notification
-                                               break;
-                                       }
-                               }
+               if(is_array($comments)) {
+                       foreach($comments as $cmnt) fb_consume_comment($a, $user, $self, $self_id, $wall, $orig_post, $cmnt);
+                       if ($sync_comments) {
+                           $r = q("SELECT COUNT(*) comments FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d AND `verb` = '%s' AND `parent-uri` != `uri`",
+                    dbesc($orig_post['uri']),
+                    intval($uid),
+                    ACTIVITY_POST
+                );
+                           if ($r[0]['comments'] < $comments_num) {
+                    logger('fb_consume_stream: missing comments found for ' . $orig_post['uri'] . ' (we have ' . $r[0]['comments'] . ' of ' . $comments_num . '). Synchronizing...', LOGGER_DEBUG);
+                    $needs_sync = true;
+                }
                        }
                }
+
+               if ($needs_sync) fb_consume_status($a, $user, $entry, $self, $self_id, $wall, $orig_post);
        }
 }
 
 
+/**
+ * @return bool|string
+ */
 function fb_get_app_access_token() {
        
        $acc_token = get_config('facebook','app_access_token');
@@ -1697,6 +1939,9 @@ function facebook_subscription_del_users() {
        if (!facebook_check_realtime_active()) del_config('facebook', 'realtime_active');
 }
 
+/**
+ * @param bool $second_try
+ */
 function facebook_subscription_add_users($second_try = false) {
        $a = get_app();
        $access_token = fb_get_app_access_token();
@@ -1733,6 +1978,9 @@ function facebook_subscription_add_users($second_try = false) {
        };
 }
 
+/**
+ * @return null|array
+ */
 function facebook_subscriptions_get() {
        
        $access_token = fb_get_app_access_token();
@@ -1749,6 +1997,9 @@ function facebook_subscriptions_get() {
 }
 
 
+/**
+ * @return bool
+ */
 function facebook_check_realtime_active() {
        $ret = facebook_subscriptions_get();
        if (is_null($ret)) return false;
@@ -1762,7 +2013,14 @@ function facebook_check_realtime_active() {
 // DELETE-request to $url
 
 if(! function_exists('facebook_delete_url')) {
-function facebook_delete_url($url,$headers = null, &$redirects = 0, $timeout = 0) {
+    /**
+     * @param string $url
+     * @param null|array $headers
+     * @param int $redirects
+     * @param int $timeout
+     * @return bool|string
+     */
+    function facebook_delete_url($url,$headers = null, &$redirects = 0, $timeout = 0) {
        $a = get_app();
        $ch = curl_init($url);
        if(($redirects > 8) || (! $ch)) 
@@ -1833,7 +2091,7 @@ function facebook_delete_url($url,$headers = null, &$redirects = 0, $timeout = 0
         $url_parsed = @parse_url($url);
         if (isset($url_parsed)) {
             $redirects++;
-            return delete_url($url,$headers,$redirects,$timeout);
+            return facebook_delete_url($url,$headers,$redirects,$timeout);
         }
     }
        $a->set_curl_code($http_code);
diff --git a/facebook_restrict.tgz b/facebook_restrict.tgz
new file mode 100644 (file)
index 0000000..7688fd8
Binary files /dev/null and b/facebook_restrict.tgz differ
diff --git a/facebook_restrict/facebook_restrict.php b/facebook_restrict/facebook_restrict.php
new file mode 100644 (file)
index 0000000..a30d880
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Name: Facebook Restrict
+ * Description: Install this addon and Facebook users will not be able to link friends. Existing users that are linking friends will not be affected.
+ * Version: 1.0
+ * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
+ */
+
+
+function facebook_restrict_install() {
+       set_config('facebook','restrict',1);
+}
+
+function facebook_restrict_uninstall() {
+       set_config('facebook','restrict',0);
+}
+
index 3e4ecd75b430a1926d3547728f019b70f397febb..d87f17f712fb524ed8467fb51daccf44fd7f3023 100755 (executable)
Binary files a/impressum.tgz and b/impressum.tgz differ
index 849c11f976cb3237960caab62d99a48ccea4aca7..901df73fa360fb4ffaefcf81bed2b387a95134bd 100755 (executable)
@@ -1,7 +1,7 @@
 {{ inc field_input.tpl with $field=$owner }}{{ endinc }}
 {{ inc field_input.tpl with $field=$ownerprofile }}{{ endinc }}
-{{ inc field_input.tpl with $field=$postal }}{{ endinc }}
-{{ inc field_input.tpl with $field=$notes }}{{ endinc }}
+{{ inc field_textarea.tpl with $field=$postal }}{{ endinc }}
+{{ inc field_textarea.tpl with $field=$notes }}{{ endinc }}
 {{ inc field_input.tpl with $field=$email }}{{ endinc }}
-{{ inc field_input.tpl with $field=$footer_text }}{{ endinc }}
+{{ inc field_textarea.tpl with $field=$footer_text }}{{ endinc }}
 <div class="submit"><input type="submit" name="page_site" value="$submit" /></div>
index 7600227907a63964378fa030658ca7601471551f..a4e7199c970c66b26237c39e713b9b9425a327c0 100755 (executable)
@@ -2,11 +2,13 @@
 /**
  * Name: Impressum
  * Description: Plugin to add contact information to the about page (/friendica)
- * Version: 1.1
+ * Version: 1.2
  * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
  * License: 3-clause BSD license
  */
 
+require_once('include/bbcode.php');
+
 function impressum_install() {
     register_hook('about_hook', 'addon/impressum/impressum.php', 'impressum_show');
     register_hook('page_end', 'addon/impressum/impressum.php', 'impressum_footer');
@@ -24,7 +26,7 @@ function obfuscate_email ($s) {
     return $s;
 }
 function impressum_footer($a, &$b) {
-    $text = get_config('impressum','footer_text');
+    $text = bbcode(get_config('impressum','footer_text'), true);
     if (! $text == '') {
         $a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="'.$a->get_baseurl().'/addon/impressum/impressum.css" media="all" />';
         $b .= '<div id="impressum_footer">'.$text.'</div>';
@@ -34,8 +36,8 @@ function impressum_show($a,&$b) {
     $b .= '<h3>'.t('Impressum').'</h3>';
     $owner = get_config('impressum', 'owner');
     $owner_profile = get_config('impressum','ownerprofile');
-    $postal = get_config('impressum', 'postal');
-    $notes = get_config('impressum', 'notes');
+    $postal = bbcode(get_config('impressum', 'postal'), true);
+    $notes = bbcode(get_config('impressum', 'notes'), true);
     $email = obfuscate_email( get_config('impressum','email') );
     if (strlen($owner)) {
         if (strlen($owner_profile)) {
@@ -66,12 +68,12 @@ function impressum_plugin_admin_post (&$a) {
     $notes = ((x($_POST, 'notes')) ? (trim($_POST['notes'])) : '');
     $email = ((x($_POST, 'email')) ? notags(trim($_POST['email'])) : '');
     $footer_text = ((x($_POST, 'footer_text')) ? (trim($_POST['footer_text'])) : '');
-    set_config('impressum','owner',$owner);
-    set_config('impressum','ownerprofile',$ownerprofile);
-    set_config('impressum','postal',$postal);
-    set_config('impressum','email',$email);
-    set_config('impressum','notes',$notes);
-    set_config('impressum','footer_text',$footer_text);
+    set_config('impressum','owner',strip_tags($owner));
+    set_config('impressum','ownerprofile',strip_tags($ownerprofile));
+    set_config('impressum','postal',strip_tags($postal));
+    set_config('impressum','email',strip_tags($email));
+    set_config('impressum','notes',strip_tags($notes));
+    set_config('impressum','footer_text',strip_tags($footer_text));
     info( t('Settings updated.'). EOL );
 }
 function impressum_plugin_admin (&$a, &$o) {
@@ -80,9 +82,9 @@ function impressum_plugin_admin (&$a, &$o) {
         '$submit' => t('Submit'),
         '$owner' => array('owner', t('Site Owner'), get_config('impressum','owner'), t('The page operators name.')),
         '$ownerprofile' => array('ownerprofile', t('Site Owners Profile'), get_config('impressum','ownerprofile'), t('Profile address of the operator.')),
-        '$postal' => array('postal', t('Postal Address'), get_config('impressum','postal'), t('How to contact the operator via snail mail.')),
-        '$notes' => array('notes', t('Notes'), get_config('impressum','notes'), t('Additional notes that are displayed beneath the contact information.')),
+        '$postal' => array('postal', t('Postal Address'), get_config('impressum','postal'), t('How to contact the operator via snail mail. You can use BBCode here.')),
+        '$notes' => array('notes', t('Notes'), get_config('impressum','notes'), t('Additional notes that are displayed beneath the contact information. You can use BBCode here.')),
         '$email' => array('email', t('Email Address'), get_config('impressum','email'), t('How to contact the operator via email. (will be displayed obfuscated)')),
-        '$footer_text' => array('footer_text', t('Footer note'), get_config('impressum','footer_text'), t('Text for the footer.')),
+        '$footer_text' => array('footer_text', t('Footer note'), get_config('impressum','footer_text'), t('Text for the footer. You can use BBCode here.')),
     ));
 }
diff --git a/jappixmini.tgz b/jappixmini.tgz
new file mode 100644 (file)
index 0000000..c7fc99a
Binary files /dev/null and b/jappixmini.tgz differ
diff --git a/jappixmini/MIT.txt b/jappixmini/MIT.txt
new file mode 100644 (file)
index 0000000..2517727
--- /dev/null
@@ -0,0 +1,7 @@
+You may distribute all files which are not within the jappix/ folder under the following conditions:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/jappixmini/README b/jappixmini/README
new file mode 100644 (file)
index 0000000..f21649b
--- /dev/null
@@ -0,0 +1,31 @@
+Jappix Mini Plugin
+==================
+
+This quick-and-dirty addon allows you to add a Jabber-based, Facebook-like chat
+to Friendica. It uses Jappix Mini.
+
+It is necessary to use a BOSH host - so to use this plugin, each users need to
+know the address of a BOSH host that works with his account. The BOSH server of
+the Jappix project (https://bind.jappix.com/) is not locked to a specific XMPP
+provider, but keep in mind that only personal usage is approved according to
+http://codingteam.net/project/jappix/doc/BoshServer.
+If you have a larger server, it is recommended that you install your own BOSH
+server and recommend it using the configuration help field. If it is on the
+same server, you can also deactivate the BOSH proxy. This should improve the
+performance.
+
+The addon has an experimental autosubscribe and autosuggest functionality which
+tries to add your Friendica contacts to your roster automatically.
+
+Limitations:
+ - Jabber passwords can only be encrypted if they are at most 39 characters
+   long.
+
+Notes on the license
+--------------------
+
+The license of this addon is AGPL, as required by Jappix Mini. If you make
+modifications to the addon, you are responsible for providing a proper facility
+for downloading the changed source code.
+Moreover, it may be necessary that you publish the source code of the Friendica
+application and all other used addons if you do not use standard versions.
diff --git a/jappixmini/jappix/AUTHORS b/jappixmini/jappix/AUTHORS
new file mode 100644 (file)
index 0000000..0086eb6
--- /dev/null
@@ -0,0 +1,54 @@
+Jappix - An open social platform
+These are the authors of Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/01/12
+
+-------------------------------------------------
+
+Here are the Jappix contributors, who coded or translated the application (Codingteam.net nicknames):
+
+# DEVELOPERS
+       - am0ur3ux
+       - LinkMauve
+       - Maranda
+       - Mathieui
+       - Olivier
+       - sim6
+       - Vanaryon
+
+# TRANSLATORS
+       - allan
+       - Arsimael
+       - Belzeneph
+       - Catdarko
+       - Cerritus
+       - chunzu
+       - ebraminio
+       - Finkregh
+       - hamano
+       - JanCBorchardt
+       - jarda
+       - joeka
+       - kr2ysiek
+       - krohn
+       - Lenwe
+       - LinkMauve
+       - Liverbool
+       - lwj
+       - m1st
+       - Maime
+       - Maranda
+       - mbajur
+       - mentalo
+       - mkwm
+       - Otourly
+       - pocamon
+       - quimi
+       - sahwar
+       - Vanaryon
+       - vitalyster
+       - Zash
diff --git a/jappixmini/jappix/COPYING b/jappixmini/jappix/COPYING
new file mode 100644 (file)
index 0000000..84ae389
--- /dev/null
@@ -0,0 +1,662 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license
+for software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are
+designed to take away your freedom to share and change the works.  By
+contrast, our General Public Licenses are intended to guarantee your
+freedom to share and change all versions of a program--to make sure it
+remains free software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public
+License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further restriction,
+you may remove that term.  If a license document contains a further
+restriction but permits relicensing or conveying under this License, you
+may add to a covered work material governed by the terms of that license
+document, provided that the further restriction does not survive such
+relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have permission
+to link or combine any covered work with a work licensed under version 3
+of the GNU General Public License into a single combined work, and to
+convey the resulting work.  The terms of this License will continue to
+apply to the part which is the covered work, but the work with which it is
+combined will remain governed by version 3 of the GNU General Public
+License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new
+versions will be similar in spirit to the present version, but may differ
+in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero
+General Public License "or any later version" applies to it, you have
+the option of following the terms and conditions either of that
+numbered version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number
+of the GNU Affero General Public License, you may choose any version
+ever published by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that
+proxy's public statement of acceptance of a version permanently
+authorizes you to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                       END OF TERMS AND CONDITIONS
+
+              How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
\ No newline at end of file
diff --git a/jappixmini/jappix/INSTALL b/jappixmini/jappix/INSTALL
new file mode 100644 (file)
index 0000000..652c1be
--- /dev/null
@@ -0,0 +1,23 @@
+Jappix - An open social platform
+These are the installation instructions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/09/10
+
+-------------------------------------------------
+
+It's very simple to install Jappix on your webserver, you just have to follow these things:
+
+# INSTALLATION
+       - The HTTP server : http://codingteam.net/project/jappix/doc/HttpServer
+       - The XMPP server : http://codingteam.net/project/jappix/doc/XmppServer
+       - The BOSH server : http://codingteam.net/project/jappix/doc/BoshServer
+       - The Jappix app. : http://codingteam.net/project/jappix/doc/JappixApp
+
+# MORE
+       - The whole documentation is available at : http://codingteam.net/project/jappix/doc
+
+Now, you can use Jappix. Happy socializing!
diff --git a/jappixmini/jappix/README b/jappixmini/jappix/README
new file mode 100644 (file)
index 0000000..49cbf97
--- /dev/null
@@ -0,0 +1,20 @@
+Jappix - An open social platform
+This is the readme file for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 18/02/11
+
+-------------------------------------------------
+
+Please refer to the installation instructions that are located in the INSTALL file to process the Jappix installation.
+
+The Jappix Project official service:  https://www.jappix.com/
+The Jappix Project website:          https://project.jappix.com/
+The Jappix Project panel:            http://codingteam.net/project/jappix
+
+Jappix is released under the terms of the AGPL license. See COPYING for details.
+
+Have fun with Jappix!
diff --git a/jappixmini/jappix/THANKS b/jappixmini/jappix/THANKS
new file mode 100644 (file)
index 0000000..a5b1222
--- /dev/null
@@ -0,0 +1,27 @@
+Jappix - An open social platform
+These are the special thanks for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/02/11
+
+-------------------------------------------------
+
+We would like to thanks the authors of these tools, coming from other projects:
+
+# PROJECTS
+       - Base64                http://rumkin.com
+       - DrawSVGChart          http://codingteam.net/project/codingteam
+       - idzXHR                http://www.iadvize.com/plugin_strophe_xmpp.html
+       - JSJaC                 http://blog.jwchat.org/jsjac/
+       - jQuery                http://jquery.com/
+       - jQuery Form           http://jquery.malsup.com/form/
+       - jQuery Timers         http://plugins.jquery.com/project/timers
+       - jXHR                  http://mulletxhr.com/
+       - Mobile Detect         http://code.google.com/p/php-mobile-detect/
+       - JSMin                 http://github.com/rgrove/jsmin-php/
+       - PHP-gettext           https://launchpad.net/php-gettext       
+       - Silk icons            http://www.famfamfam.com/lab/icons/silk/
+       - Smileys               http://www.gajim.org/
diff --git a/jappixmini/jappix/VERSION b/jappixmini/jappix/VERSION
new file mode 100644 (file)
index 0000000..7689259
--- /dev/null
@@ -0,0 +1 @@
+Spaco [0.9]
diff --git a/jappixmini/jappix/css/adhoc.css b/jappixmini/jappix/css/adhoc.css
new file mode 100644 (file)
index 0000000..68d0383
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+
+Jappix - An open social platform
+This is the Ad-Hoc CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 20/12/10
+
+*/
+
+#adhoc .content {
+       padding: 10px 0 10px 0;
+}
+
+#adhoc .adhoc-head {
+       background-color: #f1f6fd;
+       border: 1px #9dc4fc solid;
+       width: 598px;
+       height: 18px;
+       font-size: 0.9em;
+       margin: 0 10px 12px 10px;
+       padding: 6px 10px;
+}
diff --git a/jappixmini/jappix/css/anonymous.css b/jappixmini/jappix/css/anonymous.css
new file mode 100644 (file)
index 0000000..f61a79c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+
+Jappix - An open social platform
+This is the anonymous mode CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 06/11/10
+
+*/
+
+#top-content {
+       min-width: 500px !important;
+}
+
+#main-content {
+       min-width: 490px !important;
+       min-height: 450px !important;
+}
+
+#left-content {
+       display: none;
+}
+
+#right-content {
+       left: 0;
+}
diff --git a/jappixmini/jappix/css/archives.css b/jappixmini/jappix/css/archives.css
new file mode 100644 (file)
index 0000000..5e60a8b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+
+Jappix - An open social platform
+This is the archives CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 19/12/10
+
+*/
+
+#archives .content {
+       padding: 10px 0 10px 0;
+}
+
+#archives .filter {
+       background-color: #e9f1fd;
+       border-right: 1px solid #9dc4fc;
+       width: 180px;
+       padding: 12px;
+       position: absolute;
+       top: 0;
+       left: 0;
+       bottom: 0;
+       float: left;
+       border-top-left-radius: 4px;
+       border-bottom-left-radius: 4px;
+       -moz-border-radius-topleft: 4px;
+       -moz-border-radius-bottomleft: 4px;
+       -webkit-border-top-left-radius: 4px;
+       -webkit-border-bottom-left-radius: 4px;
+}
+
+#archives .filter .friend {
+       margin-bottom: 12px;
+}
+
+#archives .filter .friend {
+       height: 210px;
+       width: 180px;
+       float: none;
+}
+
+#archives .current,
+#archives .logs {
+       position: absolute;
+       bottom: 0;
+       right: 0;
+       left: 204px;
+}
+
+#archives .current {
+       background-color: #e4eef9;
+       border-bottom: 1px solid #9dc4fc;
+       font-size: 0.9em;
+       height: 16px;
+       padding: 6px;
+       top: 0;
+}
+
+#archives .current span {
+       height: 16px;
+       overflow: hidden;
+}
+
+#archives .current .name {
+       max-width: 160px;
+       font-weight: bold;
+       float: left;
+}
+
+#archives .current .time {
+       color: #47646a;
+       font-size: 0.95em;
+       float: right;
+}
+
+#archives .logs {
+       color: black;
+       font-size: 0.9em;
+       overflow: auto;
+       padding: 8px 10px 0;
+       float: left;
+       position: absolute;
+       top: 29px;
+}
+
+#archives .logs a {
+       color: black;
+       text-decoration: underline;
+}
diff --git a/jappixmini/jappix/css/board.css b/jappixmini/jappix/css/board.css
new file mode 100644 (file)
index 0000000..91e6dcf
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+
+Jappix - An open social platform
+This is the board CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+#board .one-board {
+       display: none;
+       position: fixed;
+       top: 0;
+       left: 0;
+       right: 0;
+       height: 18px;
+       z-index: 10000;
+       font-size: 0.92em;
+       padding: 6px 8px;
+       box-shadow: 0 0 8px #5c5c5c;
+       -moz-box-shadow: 0 0 8px #5c5c5c;
+       -webkit-box-shadow: 0 0 8px #5c5c5c;
+}
+
+#board .one-board:hover {
+       cursor: pointer;
+}
+
+#board .one-board.visible {
+       display: block;
+}
+
+#board .one-board.error {
+       background-color: rgb(241,160,160);
+       background-color: rgba(241,160,160,0.9);
+       color: #420c0c;
+}
+
+#board .one-board.info {
+       background-color: rgb(248,246,186);
+       background-color: rgba(248,246,186,0.9);
+       color: #2f2a02;
+}
diff --git a/jappixmini/jappix/css/buddylist.css b/jappixmini/jappix/css/buddylist.css
new file mode 100644 (file)
index 0000000..3bfa70c
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+Jappix - An open social platform
+This is the buddy-list CSS stylesheet for Jappix
+-------------------------------------------------
+License: AGPL
+Author: Vanaryon
+Last revision: 31/08/11
+*/
+#buddy-list {
+        background-color: rgb(20,20,20);
+        background-color: rgba(20,20,20,0.85);
+        color: #919191;
+        padding: 15px 6px 4px 6px;
+        border-radius: 4px;
+        -moz-border-radius: 4px;
+        -webkit-border-radius: 4px;
+        box-shadow: 0 0 6px #5c5c5c;
+        -moz-box-shadow: 0 0 6px #5c5c5c;
+        -webkit-box-shadow: 0 0 6px #5c5c5c;
+}
+#buddy-list .content {
+       background: #e8f1f3;
+       background: -moz-linear-gradient(top, #e8f1f3, #e4edef);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e8f1f3), to(#e4edef));
+        color: #666666;
+        height: 207px;
+        padding: 4px 4px 0 4px;
+        overflow-x: hidden;
+        overflow-y: auto;
+        border-top-left-radius: 3px;
+        border-top-right-radius: 3px;
+        -moz-border-radius-topleft: 3px;
+        -moz-border-radius-topright: 3px;
+        -webkit-border-top-left-radius: 3px;
+        -webkit-border-top-right-radius: 3px;
+}
+#buddy-list .one-group {
+        margin-bottom: 10px;
+}
+#buddy-list .one-group a.group {
+        color: #202c2f;
+        font-size: 0.8em;
+        margin: 3px 6px;
+        padding-left: 12px;
+        max-height: 15px;
+        text-decoration: none;
+        overflow: hidden;
+        display: block;
+}
+#buddy-list .one-group a.group.plus {
+        background-position: -4px -1143px;
+}
+#buddy-list .one-group a.group.minus {
+        background-position: -4px -1162px;
+}
+#buddy-list .one-group a.group:hover {
+        cursor: pointer;
+}
+#buddy-list .hidden-buddy,
+#buddy-list .foot-edit-finish,
+.buddy-conf-more-display-available {
+        display: none;
+}
+#buddy-list .buddy {
+        width: 100%;
+        height: 50px;
+        margin-bottom: 4px;
+}
+#buddy-list .buddy-click {
+        background: #d9e7ea;
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+        border-radius: 3px;
+        -moz-border-radius: 3px;
+        -webkit-border-radius: 3px;
+}
+#buddy-list .buddy-click:hover,
+#buddy-list .buddy-click:focus {
+        background: #cedee1;
+        cursor: pointer;
+}
+#buddy-list .buddy-click:active {
+        background: #c3d3d7;
+}
+#buddy-list .gateway {
+        height: 27px;
+}
+#buddy-list .gateway .name {
+        margin-left: 0;
+}
+#buddy-list .gateway .buddy-presence {
+        float: left;
+        overflow: hidden;
+        width: 0;
+        margin: 0 4px;
+}
+#buddy-list .avatar-container {
+        float: left;
+        text-align: center;
+        margin: 3px;
+        width: 46px;
+        height: 46px;
+}
+#buddy-list .avatar {
+        max-width: 44px;
+        max-height: 44px;
+}
+#buddy-list .name {
+        margin: 4px 3px 5px 56px;
+}
+#buddy-list .buddy-name {
+        height: 17px;
+        font-weight: bold;
+        font-size: 0.8em;
+        color: #264249;
+        margin: 5px 0 5px 2px;
+        overflow: hidden;
+}
+#buddy-list .buddy.blocked p.buddy-name {
+        text-decoration: line-through;
+}
+#buddy-list .buddy-presence {
+        height: 14px;
+        font-size: 0.7em;
+        color: #3a585e;
+        padding: 2px 0 0 16px;
+        margin-top: -3px;
+}
+#buddy-list .unavailable,
+#page-switch .unavailable,
+#page-engine p.bc-infos span.show.unavailable {
+        background-position: 0 -153px;
+}
+#buddy-list .available,
+#page-engine p.bc-infos span.show.available,
+#page-engine .list .available,
+#page-engine .list .chat,
+#page-switch .available,
+#my-infos .f-presence a[data-value=available] span {
+        background-position: 0 -169px;
+}
+#buddy-list .away,
+#page-engine p.bc-infos span.show.away,
+#page-engine .list .away,
+#page-switch .away,
+#my-infos .f-presence a[data-value=away] span {
+        background-position: 0 -185px;
+}
+#buddy-list .busy,
+#page-engine p.bc-infos span.show.busy,
+#page-engine .list .xa,
+#page-engine .list .dnd,
+#page-switch .busy,
+#my-infos .f-presence a[data-value=xa] span {
+        background-position: 0 -201px;
+}
+#buddy-list .error,
+#page-switch .error,
+#page-engine p.bc-infos span.show.error {
+        background-position: 0 -217px;
+}
+#buddy-list .buddy-infos {
+       position: absolute;
+        z-index: 100;
+        width: 337px;
+        color: white;
+        font-size: 0.8em;
+}
+.buddy-infos-subarrow {
+        background-position: 0 -241px;
+        opacity: 0.8;
+        width: 9px;
+        height: 20px;
+        margin-top: 12px;
+        float: left;
+}
+.buddy-infos-subitem {
+        background-color: rgb(0,0,0);
+        background-color: rgba(0,0,0,0.8);
+        padding: 8px 10px;
+        width: 308px;
+        text-shadow: 0 1px 1px black;
+        float: left;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+.manage-infos p.bm-authorize,
+#rosterx .oneresult span.action.add {
+        background-position: 0 -1181px;
+}
+.manage-infos p.bm-remove,
+#rosterx .oneresult span.action.delete,
+#attach div.one-file a.remove {
+        background-position: 0 -1200px;
+}
+.manage-infos p.bm-remove {
+        margin-bottom: 18px;
+}
+.manage-infos p.bm-rename {
+        background-position: 0 -1216px;
+}
+.manage-infos p.bm-group {
+        background-position: 0 -1241px;
+}
+.manage-infos div.bm-choose {
+        max-height: 95px;
+        margin: 0 0 8px 102px;
+        overflow: auto;
+}
+.manage-infos div.bm-choose label {
+        float: left;
+        clear: both;
+        margin-bottom: 1px;
+}
+.manage-infos div.bm-choose input {
+        float: left;
+}
+.manage-infos div.bm-choose input[type=checkbox] {
+        margin: 0 6px 0 0;
+}
+.manage-infos div.bm-choose div {
+        clear: both;
+}
+.manage-infos p.bm-rename,
+.manage-infos p.bm-group {
+        height: 26px;
+}
+.manage-infos p.bm-rename label,
+.manage-infos p.bm-group label {
+        width: 80px;
+        padding-top: 3px;
+        float: left;
+}
+.manage-infos p.bm-rename input,
+.manage-infos p.bm-group input {
+        float: left;
+        width: 155px;
+}
+.manage-infos a.save {
+        float: right;
+        margin: 4px;
+}
+.buddy-infos-subitem p {
+        margin: 6px 0;
+        padding-left: 22px;
+        height: 16px;
+        overflow: hidden;
+}
+.buddy-infos-subitem a {
+        color: white;
+        text-decoration: underline;
+}
+.tune-note {
+        background-position: 0 -676px;
+}
+.location-world {
+        background-position: 0 -658px;
+}
+.view-individual {
+        background-position: 0 -34px;
+}
+.edit-buddy {
+        background-position: 0 -1008px;
+}
+#buddy-list .filter {
+        background-color: white;
+        border-top: 1px solid #b8c2c4;
+        height: 15px;
+        padding: 2px 4px;
+        font-size: 0.8em;
+        border-bottom-left-radius: 3px;
+        border-bottom-right-radius: 3px;
+        -moz-border-radius-bottomleft: 3px;
+        -moz-border-radius-bottomright: 3px;
+        -webkit-border-bottom-left-radius: 3px;
+        -webkit-border-bottom-right-radius: 3px;
+}
+#buddy-list .filter input {
+        border: none;
+        color: #273a3f;
+        width: 211px;
+        padding: 0;
+        box-shadow: none;
+        -moz-box-shadow: none;
+        -webkit-box-shadow: none;
+}
+#buddy-list .filter a {
+        display: none;
+        background-color: #9a2d2d;
+        color: white;
+        height: 13px;
+        width: 13px;
+        margin-top: 1px;
+        font-size: 0.8em;
+        text-align: center;
+        text-decoration: none;
+        float: right;
+        border-radius: 2px;
+        -moz-border-radius: 2px;
+        -webkit-border-radius: 2px;
+}
+#buddy-list .filter a:hover,
+#buddy-list .filter a:focus {
+        background-color: #8c2121;
+}
+#buddy-list .filter a:active {
+        background-color: #7e1919;
+}
+#buddy-list .foot {
+        padding: 9px 1px 3px;
+}
+#buddy-list .buddy-list-icon {
+        height: 16px;
+        width: 16px;
+        margin: -3px 5px 0 0;
+        float: left;
+}
+#buddy-list .buddy-list-icon a.talk-images {
+        height: 16px;
+        width: 16px;
+        display: block;
+}
+#buddy-list .add,
+#page-engine .text .tools-add {
+        background-position: 0 -1047px;
+}
+#buddy-list .join {
+        background-position: 0 -1065px;
+}
+#buddy-list .groupchat,
+#page-switch .groupchat-default {
+        background-position: 0 -1082px;
+}
+#buddy-list .more {
+        background-position: 0 -1100px;
+}
+#buddy-list .foot-edit-finish a {
+        color: white;
+        font-size: 0.8em;
+        margin: -3px 4px 0 0;
+        float: right;
+        display: block;
+}
+#buddy-list .foot-edit-finish a:hover,
+#buddy-list .foot-edit-finish a:focus {
+        text-decoration: underline;
+        cursor: pointer;
+}
+.buddy-conf-item {
+        position: absolute;
+        width: 263px;
+        color: white;
+        z-index: 9998;
+        text-align: left;
+        font-size: 0.8em;
+        margin-left: -10px;
+}
+.buddy-conf-item:hover {
+        cursor: default;
+}
+.buddy-conf-subarrow {
+        background-position: 0 -241px;
+        opacity: 0.8;
+        height: 10px;
+        width: 18px;
+        margin-left: 9px;
+}
+.buddy-conf-subitem {
+        background-color: rgb(0,0,0);
+        background-color: rgba(0,0,0,0.8);
+        padding: 10px;
+        text-shadow: 0 1px 1px black;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+.buddy-conf-p {
+        margin-bottom: 4px;
+        width: 220px;
+        font-weight: bold;
+        float: left;
+}
+.buddy-conf-input {
+        padding-top: 2px;
+}
+.buddy-conf-text {
+        font-size: 11px;
+        clear: both;
+        margin-bottom: 3px;
+}
+.buddy-conf-text a {
+        color: white;
+}
+.buddy-conf-text a:hover,
+.buddy-conf-text a:focus {
+        cursor: pointer;
+        text-decoration: underline;
+}
+.buddy-conf-text a.buddy-conf-add-search {
+        text-decoration: underline;
+        margin-top: 6px;
+        display: block;
+}
+.buddy-conf-select {
+        font-size: 1.1em;
+        clear: both;
+        margin-bottom: 8px;
+        width: 180px;
+        height: 23px;
+}
+.join-jid {
+        width: 220px;
+        margin-top: 5px;
+}
+.add-contact-jid,
+.add-contact-name,
+.add-contact-gateway {
+        width: 156px;
+        margin-bottom: 4px;
+}
+.add-contact-name-get {
+        font-size: 0.8em;
+        display: none;
+}
+.buddy-conf-subitem label {
+        clear: both;
+}
+.buddy-conf-subitem label span {
+        width: 76px;
+        height: 14px;
+        margin-top: 3px;
+        overflow: hidden;
+        float: left;
+}
+#buddy-conf-join ul {
+        width: 224px;
+        max-height: 160px;
+        left: 10px;
+        top: 51px;
+}
+.buddy-conf-join-select {
+        margin: 8px 0 0 0;
+}
diff --git a/jappixmini/jappix/css/channel.css b/jappixmini/jappix/css/channel.css
new file mode 100644 (file)
index 0000000..671d25e
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+
+Jappix - An open social platform
+This is the channel CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+#channel .top div.update {
+       position: absolute;
+       top: 12px;
+       left: 115px;
+       right: 15px;
+       bottom: 15px;
+       border-radius: 20px;
+       -moz-border-radius: 20px;
+       -webkit-border-radius: 20px;
+}
+
+#channel .top p {
+       font-size: 0.9em;
+       margin-bottom: 10px;
+}
+
+#channel .top h2 {
+       font-size: 1.6em;
+       margin-bottom: 10px;
+       color: #232323;
+}
+
+#channel .top a {
+       font-size: 0.9em;
+       color: #232323;
+}
+
+#channel .top.individual div.update {
+       right: 36px;
+}
+
+#channel .top.individual div.shortcuts,
+#userinfos .main-infos div.shortcuts {
+       width: 16px;
+       float: right;
+}
+
+#channel .top.individual div.shortcuts {
+       margin: 2px 5px 0 0;
+}
+
+#channel .top.individual div.shortcuts a,
+#userinfos .main-infos div.shortcuts a {
+       height: 16px;
+       width: 16px;
+       margin-bottom: 4px;
+       display: block;
+}
+
+#channel .top.individual div.shortcuts a.message,
+#userinfos .main-infos a.message {
+       background-position: 0 -1717px;
+}
+
+#channel .top.individual div.shortcuts a.chat,
+#userinfos .main-infos a.chat {
+       background-position: 0 -1737px;
+}
+
+#channel .top.individual div.shortcuts a.command,
+#userinfos .main-infos a.command {
+       background-position: 0 -1758px;
+}
+
+#channel .microblog-body {
+       height: 20px;
+       margin-right: 50px;
+}
+
+#channel .microblog-body input {
+       width: 100%;
+       height: 100%;
+       padding: 8px;
+}
+
+#channel .one-microblog-icon {
+       position: absolute;
+       top: 38px;
+       right: 0;
+}
+
+#channel div.update .one-microblog-icon,
+#channel div.update .postit {
+       width: 16px;
+       height: 16px;
+       display: block;
+}
+
+#channel div.update .attach {
+       background-position: 0 -79px;
+       display: none;
+}
+
+#attach {
+       position: absolute;
+       width: 263px;
+       margin-left: -227px;
+       color: white;
+       font-size: 0.85em;
+       z-index: 9998;
+       text-align: left;
+       display: none;
+}
+
+#attach p {
+       margin-bottom: 6px !important;
+}
+
+#attach input[type=submit] {
+       margin: 8px 0 6px 0;
+}
+
+#attach .wait {
+       float: right;
+       margin: 7px 5px;
+}
+
+#attach div.one-file {
+       height: 16px;
+       margin-top: 2px;
+}
+
+#attach div.one-file a.link {
+       color: white;
+       width: 215px;
+       height: 14px;
+       margin-left: 2px;
+       overflow: hidden;
+       float: left;
+}
+
+#attach div.one-file a.remove {
+       width: 16px;
+       height: 16px;
+       float: left;
+}
+
+.attach-subarrow {
+       background-position: 0 -241px;
+       opacity: 0.8;
+       height: 10px;
+       width: 18px;
+       margin-left: 226px;
+}
+
+.attach-subitem {
+       background-color: rgb(0,0,0);
+       background-color: rgba(0,0,0,0.8);
+       padding: 10px;
+       text-shadow: 0 1px 1px black;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+
+.attach-p {
+       font-weight: bold;
+       float: left;
+}
+
+#channel .one-update {
+       margin-bottom: 12px;
+       padding: 6px 6px 8px 6px;
+       border-bottom: 1px dotted #d0d0d0;
+       min-height: 50px;
+       color: black;
+       position: relative;
+       display: none;
+}
+
+#channel .one-update .avatar-container {
+       text-align: center;
+       margin-right: 16px;
+       float: left;
+       height: 50px;
+       width: 50px;
+}
+
+#channel .one-update .avatar-container:hover {
+       cursor: pointer;
+}
+
+#channel .one-update img.avatar {
+       max-height: 50px;
+       max-width: 50px;
+}
+
+#channel .one-update div.body {
+       margin-left: 65px;
+       opacity: 0.8;
+}
+
+#channel .one-update:hover div.body {
+       opacity: 1;
+}
+
+#channel .one-update a.repeat {
+       background-position: 0 -1681px;
+       height: 16px;
+       width: 16px;
+       margin-right: 4px;
+       float: left;
+}
+
+#channel .one-update span a {
+       text-decoration: underline;
+}
+
+#channel .one-update p {
+       display: block;
+       margin: 0 12px 5px 0;
+}
+
+#channel .one-update p b.name:hover {
+       cursor: pointer;
+       text-decoration: underline;
+}
+
+#channel .one-update p.infos {
+       font-size: 0.9em;
+}
+
+#channel .one-update p.infos a.geoloc {
+       background-position: 0 -1778px;
+       color: #363636;
+       margin-left: 18px;
+       padding-left: 14px;
+}
+
+#channel .one-update p.infos a.geoloc:hover,
+#channel .one-update p.infos a.geoloc:focus,
+#channel .one-update p.infos a.geoloc:active {
+       color: #141414;
+}
+
+#channel .one-update p.file {
+       font-size: 0.9em;
+       margin: 6px 0 5px 10px;
+}
+
+#channel .one-update p.file a.link,
+#inbox .inbox-new-file a.file {
+       min-height: 16px;
+       padding-left: 22px;
+       text-decoration: underline;
+       display: block;
+}
+
+#channel .one-update p.file a.link {
+       margin-top: 4px;
+}
+
+#channel p.file a,
+#inbox .inbox-new-file a.file {
+       background-position: 0 -988px;
+}
+
+#channel p.file a.audio,
+#inbox .inbox-new-file a.file.audio {
+       background-position: 0 -899px;
+}
+
+#channel p.file a.image,
+#inbox .inbox-new-file a.file.image {
+       background-position: 0 -917px;
+}
+
+#channel p.file a.video,
+#inbox .inbox-new-file a.file.video {
+       background-position: 0 -935px;
+}
+
+#channel p.file a.document,
+#inbox .inbox-new-file a.file.document {
+       background-position: 0 -953px;
+}
+
+#channel p.file a.package,
+#inbox .inbox-new-file a.file.package {
+       background-position: 0 -971px;
+}
+
+#channel .one-update p.file a.thumb img {
+       border: 1px solid #a2a2a2;
+       max-width: 140px;
+       max-height: 105px;
+       margin: 4px 10px 2px 0;
+       padding: 1px;
+}
+
+#channel .one-update p.file a.thumb img:hover {
+       border-color: #464646;
+}
+
+#channel .one-update div.comments,
+.popup.large div.comments {
+       width: 410px;
+       margin: 2px 0 2px 76px;
+}
+
+#channel .one-update div.comments div.arrow,
+.popup.large div.comments div.arrow {
+       background-position: 0 -1702px;
+       width: 20px;
+       height: 8px;
+       margin-left: 20px;
+       display: block;
+}
+
+#channel .one-update div.comments div.comments-content,
+.popup.large div.comments div.comments-content {
+       background-color: #e5ebec;
+       color: black;
+       font-size: 0.9em;
+       text-shadow: 0 1px 0 white;
+}
+
+#channel .one-update div.comments input,
+.popup.large div.comments input {
+       width: 356px;
+       margin: 6px 0;
+       padding: 4px 5px;
+}
+
+#channel .one-update div.comments span.icon,
+.popup.large div.comments span.icon {
+       background-position: 0 -1082px;
+       height: 16px;
+       width: 16px;
+       margin: 10px;
+       float: left;
+}
+
+#channel .one-update div.comments .one-comment.loading span.icon,
+.popup.large div.comments .one-comment.loading span.icon {
+       margin: 0 10px 0 0;
+}
+
+#channel .one-update div.comments .one-comment,
+.popup.large div.comments .one-comment {
+       border-bottom: 1px solid #f4f4f4;
+       padding: 4px 8px 0px 8px;
+       position: relative;
+       display: block;
+}
+
+#channel .one-update div.comments .one-comment.compose,
+.popup.large div.comments .one-comment.compose {
+       border-bottom: 2px solid #f4f4f4;
+       height: 36px;
+       padding: 0;
+}
+
+#channel .one-update div.comments .one-comment.new,
+.popup.large div.comments .one-comment.new {
+       display: none;
+}
+
+#channel .one-update div.comments a.one-comment,
+.popup.large div.comments a.one-comment {
+       text-decoration: none;
+}
+
+#channel .one-update div.comments a.one-comment:hover,
+#channel .one-update div.comments a.one-comment:focus,
+.popup.large div.comments a.one-comment:hover,
+.popup.large div.comments a.one-comment:focus {
+       text-decoration: underline;
+}
+
+#channel .one-update div.comments .one-comment.loading,
+.popup.large div.comments .one-comment.loading {
+       padding-bottom: 5px;
+}
+
+#channel .one-update div.comments .one-comment div.marker,
+.popup.large div.comments .one-comment div.marker {
+       background-color: #6d8387;
+       width: 2px;
+       position: absolute;
+       top: 0;
+       left: 0;
+       bottom: 0;
+}
+
+#channel .one-update div.comments .one-comment .avatar-container,
+.popup.large div.comments .one-comment .avatar-container {
+       text-align: center;
+       width: 30px;
+       height: 30px;
+       margin: 2px 8px 0 0;
+       float: left;
+}
+
+#channel .one-update div.comments .one-comment .avatar-container:hover,
+.popup.large div.comments .one-comment .avatar-container:hover {
+       cursor: pointer;
+}
+
+#channel .one-update div.comments .one-comment img.avatar,
+.popup.large div.comments .one-comment img.avatar {
+       max-height: 30px;
+       max-width: 30px;
+}
+
+#channel .one-update div.comments .one-comment .comment-container,
+.popup.large div.comments .one-comment .comment-container {
+       float: left;
+}
+
+#channel .one-update div.comments .one-comment a.name,
+.popup.large div.comments .one-comment a.name {
+       font-weight: bold;
+       text-decoration: none;
+       font-size: 0.95em;
+       padding-bottom: 2px;
+       float: left;
+}
+
+#channel .one-update div.comments .one-comment a.name:hover,
+#channel .one-update div.comments .one-comment a.name:focus,
+.popup.large div.comments .one-comment a.name:hover,
+.popup.large div.comments .one-comment a.name:focus {
+       text-decoration: underline;
+}
+
+#channel .one-update div.comments .one-comment span.date,
+#channel .one-update div.comments .one-comment a.remove,
+.popup.large div.comments .one-comment span.date,
+.popup.large div.comments .one-comment a.remove {
+       font-size: 0.85em;
+       float: right;
+}
+
+#channel .one-update div.comments .one-comment.me:hover span.date,
+.popup.large div.comments .one-comment.me:hover span.date {
+       display: none;
+}
+
+#channel .one-update div.comments .one-comment.me a.remove,
+.popup.large div.comments .one-comment.me a.remove {
+       display: none;
+}
+
+#channel .one-update div.comments .one-comment.me:hover a.remove,
+.popup.large div.comments .one-comment.me:hover a.remove {
+       display: block;
+}
+
+#channel .one-update div.comments .one-comment p.body,
+.popup.large div.comments .one-comment p.body {
+       clear: both;
+}
+
+#channel a.more {
+       background-position: 0 -334px;
+       color: black;
+       height: 16px;
+       text-decoration: none;
+       margin: -2px 0 0 4px;
+       padding: 0 0 14px 20px;
+       display: block;
+       visibility: hidden;
+}
+
+#channel a.more:hover,
+#channel a.more:focus {
+       text-decoration: underline;
+}
+
+#channel a.mbtool {
+       width: 11px;
+       height: 11px;
+       display: none;
+       position: absolute;
+       right: 0;
+}
+
+#channel .one-update:hover a.mbtool {
+       display: block;
+}
+
+#channel a.mbtool:hover,
+#channel a.mbtool:focus {
+       text-decoration: none;
+}
+
+#channel a.mbtool.profile {
+       background-position: -1px -1333px;
+       top: 24px;
+}
+
+#channel a.mbtool.repost {
+       background-position: -1px -1354px;
+}
+
+#channel a.mbtool.remove {
+       background-position: -1px -1312px;
+}
+
+#channel a.mbtool.repost,
+#channel a.mbtool.remove {
+       top: 6px;
+}
+
+#channel .footer {
+       bottom: 0;
+       border-bottom-left-radius: 4px;
+       border-bottom-right-radius: 4px;
+       -moz-border-radius-bottomleft: 4px;
+       -moz-border-radius-bottomright: 4px;
+       -webkit-border-bottom-left-radius: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+}
+
+#channel .footer div {
+       margin-left: 5px;
+       padding-left: 24px;
+       min-height: 16px;
+       font-size: 0.85em;
+       width: auto !important;
+}
+
+#channel .footer .sync {
+       background-position: 0 -804px;
+       display: none;
+}
+
+#channel .footer .unsync {
+       background-position: 0 -830px;
+       display: none;
+}
diff --git a/jappixmini/jappix/css/directory.css b/jappixmini/jappix/css/directory.css
new file mode 100644 (file)
index 0000000..34b3231
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+
+Jappix - An open social platform
+This is the directory tool CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 13/02/11
+
+*/
+
+#directory .content {
+       padding: 10px 0 10px 0;
+}
diff --git a/jappixmini/jappix/css/discovery.css b/jappixmini/jappix/css/discovery.css
new file mode 100644 (file)
index 0000000..f66456b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+
+Jappix - An open social platform
+This is the discovery CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 13/02/11
+
+*/
+
+#discovery .content {
+       padding: 10px 0 10px 0;
+}
+
+#discovery .content p {
+       margin: 5px 10px 5px 10px;
+       text-align: justify;
+       font-size: 0.85em;
+}
+
+#discovery .discovery-head,
+#directory .directory-head,
+#rosterx .rosterx-head,
+#privacy .privacy-head {
+       width: 606px;
+       height: 24px;
+       margin: 0 10px 10px 10px;
+       padding: 6px;
+       background: #f1f6fd;
+       border: 1px #9dc4fc solid;
+}
+
+#discovery .disco-server-text,
+#directory .directory-server-text {
+       float: left;
+       font-size: 0.9em;
+       margin: 3px;
+}
+
+#discovery .disco-server-input,
+#directory .directory-server-input {
+       float: right;
+       width: 200px;
+       padding: 2px;
+       height: 18px;
+       float: right;
+       margin-right: 10px;
+       padding: 2px;
+}
+
+#discovery .disco-category {
+       display: none;
+       margin-bottom: 22px;
+}
+
+#discovery .disco-category-title {
+       font-weight: bold;
+}
diff --git a/jappixmini/jappix/css/favorites.css b/jappixmini/jappix/css/favorites.css
new file mode 100644 (file)
index 0000000..5d3fd51
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+
+Jappix - An open social platform
+This is the favorites CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+#favorites .content {
+       padding: 10px 0 10px 0;
+}
+
+#favorites .fedit-head-select {
+       min-width: 190px;
+       max-width: 210px;
+}
+
+#favorites .switch-fav {
+       margin: 0 10px 0 10px;
+       width: 200px;
+       height: 355px;
+       border-right: 1px #c0c0c0 dotted;
+       float: left;
+}
+
+#favorites .room-switcher {
+       width: 188px;
+       height: 18px;
+       border-bottom: 1px #9dc4fc solid;
+       float: left;
+       padding: 10px 6px;
+       font-size: 0.9em;
+}
+
+#favorites .room-switcher:hover {
+       background-color: #e9f1fd;
+       cursor: pointer;
+}
+
+#favorites .room-switcher:active {
+       background-color: #f1f6fd;
+}
+
+#favorites .switch-fav .icon {
+       float: left;
+       height: 16px;
+       width: 16px;
+       margin: 0 8px 0 0;
+}
+
+#favorites .switch-fav .room-list .list-icon {
+       background-position: 0 -855px;
+}
+
+#favorites .switch-fav .room-search .search-icon {
+       background-position: 0 -876px;
+}
+
+#favorites .static-fav {
+       width: 385px;
+       height: 335px;
+       margin: 0 10px 0 0;
+       padding: 10px;
+       float: right;
+}
+
+#favorites .favorites-search {
+       display: none;
+}
+
+#favorites .static-fav-head {
+       width: 393px;
+       margin: -10px;
+}
+
+#favorites .static-fav-results {
+       width: 406px;
+       height: 314px;
+       margin: 10px -10px -10px -10px;
+       padding: 6px 0 0 0;
+}
+
+#favorites .fedit-line {
+       height: 30px;
+       font-size: 0.9em;
+       padding: 10px 0 4px 4px;
+       border-bottom: 1px #9dc4fc solid;
+}
+
+#favorites .fedit-line:hover {
+       background: #e9f1fd;
+}
+
+#favorites label {
+       width: 140px;
+       margin-top: 3px;
+}
+
+#favorites input {
+       height: 18px;
+       width: 186px;
+       margin-top: 0;
+       padding: 2px;
+}
+
+#favorites .fedit-select {
+       min-width: 160px;
+}
+
+#favorites .fedit-actions {
+       margin: 10px 0 0;
+       font-size: 0.9em;
+       float: right;
+}
+
+#favorites input[type=checkbox] {
+       margin-top: 5px;
+}
+
+#favorites .fedit-terminate {
+       float: right;
+}
+
+#favorites .fedit-add {
+       display: block;
+}
+
+#favorites .fedit-edit {
+       background-position: 2px -1240px;
+}
+
+#favorites .fedit-remove {
+       margin: 0 8px 0 0;
+}
+
+#favorites .add,
+.popup .results .one-button.one-add {
+       background-position: 3px -1177px;
+}
+
+#favorites .remove,
+#inbox .remove {
+       background-position: 3px -1196px;
+}
+
+#favorites .join,
+#inbox .reply,
+#inbox .send,
+.popup .results .one-button.one-chat {
+       background-position: 3px -124px;
+}
+
+#favorites .one-button,
+#inbox .one-button,
+.popup .results .one-button {
+       padding-left: 20px !important;
+       font-size: 0.98em;
+}
+
+#favorites .fsearch-results {
+       overflow: auto;
+}
+
+#favorites .room-name {
+       margin: 4px 2px 5px;
+       max-width: 210px;
+       float: left;
+}
+
+#favorites .fsearch-noresults {
+       display: none;
+       font-size: 0.9em;
+       font-weight: bold;
+}
diff --git a/jappixmini/jappix/css/home.css b/jappixmini/jappix/css/home.css
new file mode 100644 (file)
index 0000000..789ea4d
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+
+Jappix - An open social platform
+This is the home CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/01/12
+
+*/
+
+#home {
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       min-height: 550px;
+       min-width: 875px;
+}
+
+#home .corporation,
+#home .corporation .corp_network,
+#home .locale,
+#home .obsolete {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.70);
+       color: white;
+       position: absolute;
+       top: 0;
+       text-shadow: 0 0 1px black;
+       z-index: 100;
+       border-bottom-left-radius: 3px;
+       border-bottom-right-radius: 3px;
+       -moz-border-radius-bottomleft: 3px;
+       -moz-border-radius-bottomright: 3px;
+       -webkit-border-bottom-left-radius: 3px;
+       -webkit-border-bottom-right-radius: 3px;
+}
+
+#home .corporation {
+       background-position: 9px -357px;
+       left: 12px;
+       height: 26px;
+       width: 34px;
+}
+
+#home .corporation.hovered {
+       height: 28px;
+       border-radius: 0;
+       -moz-border-radius: 0;
+       -webkit-border-radius: 0;
+}
+
+#home .corporation .corp_network {
+       width: 180px;
+       padding: 10px 12px;
+       top: 28px;
+       display: none;
+       border-top-right-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -webkit-border-top-right-radius: 3px;
+}
+
+#home .corporation.hovered .corp_network {
+       display: block;
+}
+
+#home .corporation .corp_network h2 {
+       font-size: 1.1em;
+       margin: 14px 0 4px 0;
+}
+
+#home .corporation .corp_network h2.nomargin {
+       margin-top: 0;
+}
+
+#home .corporation .corp_network a {
+       font-size: 0.8em;
+       margin: 2px 0;
+       padding: 2px 6px;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+#home .corporation .corp_network a span {
+       margin: 2px 0;
+       display: block;
+}
+
+#home .corporation .corp_network a span.name {
+       font-weight: bold;
+}
+
+#home .corporation .corp_network a span.desc {
+       font-size: 0.9em;
+       margin-left: 2px;
+}
+
+#home .locale {
+       left: 52px;
+       font-size: 0.8em;
+}
+
+#home .locale .current {
+       height: 19px;
+       padding: 3px 12px 4px 12px;
+       font-weight: bold;
+}
+
+#home .locale .current:hover {
+       cursor: default;
+}
+
+#home .locale .current .current_align {
+       height: 19px;
+       vertical-align: middle;
+       display: table-cell;
+}
+
+#home .locale .list {
+       margin: 2px 0 2px;
+}
+
+#home .locale .list a,
+#home .corporation .corp_network a {
+       color: white;
+       text-decoration: none;
+       display: block;
+}
+
+#home .locale .list a {
+       padding: 3px 10px;
+}
+
+#home .locale .list a:hover,
+#home .locale .list a:focus,
+#home .corporation .corp_network a:hover,
+#home .corporation .corp_network a:focus {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+       cursor: pointer;
+}
+
+#home .locale .list a:active,
+#home .corporation .corp_network a:active {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.14);
+}
+
+#home .obsolete {
+       height: 60px;
+       padding: 4px 10px;
+       right: 12px;
+       font-size: 0.9em;
+       font-weight: bold;
+       display: none;
+}
+
+#home .obsolete a {
+       height: 33px;
+       width: 33px;
+       margin: 5px 2px 0 0;
+       float: left;
+}
+
+#home .obsolete a:hover,
+#home .obsolete a:focus {
+       opacity: 0.8;
+}
+
+#home .obsolete a:active {
+       opacity: 0.6;
+}
+
+#home .obsolete a.firefox {
+       background-position: 1px 0;
+}
+
+#home .obsolete a.chrome {
+       background-position: -34px 0;
+}
+
+#home .obsolete a.safari {
+       background-position: -68px 0;
+}
+
+#home .obsolete a.opera {
+       background-position: -101px 0;
+}
+
+#home .obsolete a.ie {
+       background-position: -135px 0;
+}
+
+#home .plane {
+       background-position: 0 -384px;
+       width: 507px;
+       height: 328px;
+       position: absolute;
+       left: 0;
+       top: 60px;
+}
+
+#home .main {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.85);
+       position: absolute;
+       top: 50%;
+       margin-top: -200px;
+       width: 800px;
+       height: 400px;
+       left: 50%;
+       margin-left: -400px;
+       z-index: 50;
+       border-radius: 10px;
+       -moz-border-radius: 10px;
+       -webkit-border-radius: 10px;
+       box-shadow: 0 0 35px #5c5c5c;
+       -moz-box-shadow: 0 0 35px #5c5c5c;
+       -webkit-box-shadow: 0 0 35px #5c5c5c;
+}
+
+#home .left {
+       float: left;
+       width: 350px;
+       height: 370px;
+       margin: 15px 0 15px 15px;
+       color: white;
+       text-align: center;
+       text-shadow: 0 1px 1px black;
+}
+
+#home .left .logo {
+       background-position: 0 0;
+       float: left;
+       margin: 30px 20px;
+       width: 311px;
+       height: 113px;
+}
+
+#home .left p.upper {
+       margin: 12px 0 20px 0;
+}
+
+#home .left p.secondary {
+       margin: 8px 0 0 16px;
+       font-size: 0.9em;
+       width: 320px;
+}
+
+#home .right {
+       background: #e4eef9;
+       background: -moz-linear-gradient(top, #e4eef9, #C5E1FF);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#C5E1FF));
+       float: right;
+       width: 385px;
+       height: 350px;
+       margin: 15px 15px 15px 0;
+       padding: 10px;
+       font-size: 13px;
+       text-align: justify;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+       box-shadow: 0 0 20px black;
+       -moz-box-shadow: 0 0 20px black;
+       -webkit-box-shadow: 0 0 20px black;
+}
+
+#home .right h1 {
+       font-size: 16px;
+       padding-bottom: 4px;
+       border-bottom: 1px black dotted;
+}
+
+#home .right p {
+       margin-bottom: 4px;
+}
+
+#home .right p a {
+       border-width: 0 0 1px 0;
+       border-style: dotted;
+       border-color: black;
+}
+
+#home .right p a:hover,
+#home .right p a:focus {
+       border-style: solid;
+       text-decoration: none;
+}
+
+#home .right button {
+       display: block;
+       margin-left: 22px;
+       width: 342px;
+       height: 64px;
+       text-decoration: none;
+       font-weight: bold;
+       border-radius: 4px;
+       -moz-border-radius: 4px;
+       -webkit-border-radius: 4px;
+}
+
+#home .right button:hover {
+       cursor: pointer;
+}
+
+#home .right button span {
+       float: left;
+}
+
+#home .right button span.home-images {
+       height: 16px;
+       width: 16px;
+       margin: 5px 7px 7px 24px;
+}
+
+#home .right button span.text {
+       padding-left: 20px;
+       font-size: 1.5em;
+}
+
+#home .right .login {
+       background-color: #72d071;
+       background-position: 0 0;
+       border: 1px solid #5cb55c;
+       margin-top: 22px;
+       box-shadow: 0 0 10px #89e389;
+       -moz-box-shadow: 0 0 10px #89e389;
+       -webkit-box-shadow: 0 0 10px #89e389;
+}
+
+#home .right .login:hover,
+#home .right .login:focus {
+       border: 1px solid #419141;
+       box-shadow: 0 0 15px #72d071;
+       -moz-box-shadow: 0 0 15px #72d071;
+       -webkit-box-shadow: 0 0 15px #72d071;
+}
+
+#home .right .login:active {
+       background-color: #97e896;
+       background-position: 0 -80px;
+}
+
+#home .right .login span.text {
+       color: #2d612d;
+       text-shadow: 1px 1px 1px #5cb55c;
+}
+
+#home .right .login span.home-images {
+       background-position: 0 -230px;
+}
+
+#home .right .register {
+       background-color: #f6ef82;
+       background-position: 0 -160px;
+       border: 1px solid #e3db56;
+       margin-top: 15px;
+       box-shadow: 0 0 15px #f1e968;
+       -moz-box-shadow: 0 0 15px #f1e968;
+       -webkit-box-shadow: 0 0 15px #f1e968;
+}
+
+#home .right .register:hover,
+#home .right .register:focus {
+       border: 1px solid #d2c93f;
+       box-shadow: 0 0 15px #e0d743;
+       -moz-box-shadow: 0 0 15px #e0d743;
+       -webkit-box-shadow: 0 0 15px #e0d743;
+}
+
+#home .right .register:active {
+       background-color: #fdf7af;
+       background-position: 0 -240px;
+}
+
+#home .right .register span.text {
+       color: #6d6813;
+       text-shadow: 1px 1px 1px #dbd56e;
+}
+
+#home .right .register span.home-images {
+       background-position: 0 -204px;
+}
+
+#home .right p.notice {
+       margin-top: 24px;
+       font-size: 0.9em;
+}
+
+#home .right .navigation {
+       clear: both;
+       width: 385px;
+       border-top: 1px black dotted;
+       position: absolute;
+       text-align: right;
+       bottom: 25px;
+       right: 25px;
+       padding-top: 6px;
+}
+
+#home .right .navigation a {
+       margin-left: 9px;
+       color: black;
+       text-decoration: none;
+       font-size: 0.9em;
+       height: 12px;
+       padding: 0 0 4px 20px;
+       float: right;
+}
+
+#home .right .navigation a:hover,
+#home .right .navigation a:focus {
+       text-decoration: underline;
+}
+
+#home .right .navigation a.unencrypted {
+       background-position: 0 -256px;
+}
+
+#home .right .navigation a.encrypted {
+       background-position: 0 -282px;
+}
+
+#home .right .navigation a.project {
+       background-position: 0 -126px;
+}
+
+#home .right .navigation a.manager {
+       background-position: 0 -152px;
+}
+
+#home .right .navigation a.mobile {
+       background-position: 0 -178px;
+}
+
+#home a.advanced {
+       background-position: 0 -334px;
+       font-size: 0.9em;
+       height: 16px;
+       margin-bottom: 10px;
+       padding-left: 16px;
+       display: block;
+}
+
+#home fieldset.advanced {
+       display: none;
+}
+
+#home .anonymouser input[type=text] {
+       width: 160px;
+}
+
+#home .homediv.registerer .success a {
+       font-weight: bold;
+       text-decoration: underline;
+}
+
+#home fieldset {
+       border: 1px solid black;
+       margin: 12px 0 12px 0;
+       padding: 5px 0 4px 0;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+#home legend {
+       font-size: 0.9em;
+       margin: 0 0 0 15px;
+       padding: 0 2px;
+       text-transform: uppercase;
+}
+
+#home label {
+       width: 110px;
+       display: block;
+       float: left;
+       clear: both;
+       margin: 0 0 5px 12px;
+}
+
+#home input,
+#home select {
+       float: left;
+       margin-bottom: 5px;
+}
+
+#home input[type=text],
+#home input[type=password],
+#home select {
+       width: 140px;
+       margin-top: -2px;
+}
+
+#home input[type=submit] {
+       min-width: 120px;
+       float: right;
+}
+
+#home span.jid {
+       display: block;
+       float: left;
+       margin: 0 4px;
+}
+
+#home input.nick, #home input.server {
+       width: 110px;
+}
+
+#home .info {
+       padding: 6px;
+       position: absolute;
+       bottom: 62px;
+       right: 35px;
+       border-width: 1px;
+       border-style: dotted;
+       clear: both;
+       width: 350px;
+}
+
+#home .info.success {
+       background-color: #aee578;
+       border-color: #85b05c;
+       display: none;
+}
+
+#home .info.fail {
+       background-color: #f19d9d;
+       border-color: #b34f4f;
+}
+
+#home .info.report {
+       background-color: #f3f48b;
+       border-color: #c9c66b;
+       display: none;
+}
+
+#home .info.report span {
+       text-decoration: underline;
+}
+
+#home .notice.simple {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.7);
+       color: white;
+       font-size: 0.9em;
+       text-decoration: none;
+       text-shadow: 0 1px 0 black;
+       position: fixed;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       padding: 8px 20px;
+       z-index: 100;
+       box-shadow: 0 0 25px #ababab;
+       -moz-box-shadow: 0 0 25px #ababab;
+       -webkit-box-shadow: 0 0 25px #ababab;
+}
+
+#home .notice.simple .title {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.4);
+       background-position: 8px -299px;
+       border-width: 0 1px 1px 1px;
+       border-style: solid;
+       border-color: #141414;
+       font-weight: bold;
+       padding: 8px 8px 8px 30px;
+}
+
+#home .notice.simple .text {
+       margin-left: 20px;
+}
diff --git a/jappixmini/jappix/css/ie.css b/jappixmini/jappix/css/ie.css
new file mode 100644 (file)
index 0000000..8808b50
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+
+Jappix - An open social platform
+These are all the IE compliant CSS classes
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 22/04/11
+
+*/
+
+/* rgba(255,255,255,0.9) */
+.search ul {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edffffff,endColorstr=#edffffff);
+}
+
+/* rgba(255,255,255,0.3) */
+a.finish:active,
+#manager-buttons input:active,
+#install-buttons input:active {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#49ffffff,endColorstr=#49ffffff);
+}
+
+/* rgba(255,255,255,0.2) */
+a.finish:hover,
+a.finish:focus,
+#manager-buttons input:hover,
+#manager-buttons input:focus,
+#install-buttons input:hover,
+#install-buttons input:focus,
+.notifications-content .one-notification:active {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#33ffffff,endColorstr=#33ffffff);
+}
+
+/* rgba(255,255,255,0.14) */
+#home .locale .list a:active {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#2fffffff,endColorstr=#2fffffff);
+}
+
+/* rgba(255,255,255,0.1) */
+#home .locale .list a:hover,
+#home .locale .list a:focus,
+a.finish,
+a.finish.disabled:hover,
+a.finish.disabled:focus,
+a.finish.disabled:active,
+#manager-buttons input,
+#install-buttons input,
+.notifications-content .one-notification:hover,
+.notifications-content .one-notification:focus {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#20ffffff,endColorstr=#20ffffff);
+}
+
+/* rgba(255,239,104,0.8) */
+.popup .infos {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#deffef68,endColorstr=#deffef68);
+}
+
+/* rgba(225,160,20,0.3) */
+.search ul li.hovered {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#46e1a014,endColorstr=#46e1a014);
+}
+
+/* rgba(248,246,186,0.9) */
+#board .one-board.info {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edf8f6ba,endColorstr=#edf8f6ba);
+}
+
+/* rgba(241,160,160,0.9) */
+#board .one-board.error {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#edf1a0a0,endColorstr=#edf1a0a0);
+}
+
+/* rgba(234,234,234,0.8) */
+#page-engine .chatstate {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#deeaeaea,endColorstr=#deeaeaea);
+}
+
+/* rgba(20,20,20,0.6) */
+#home .locale,
+#home .obsolete,
+#home .notice.simple {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#a0141414,endColorstr=#a0141414);
+}
+
+/* rgba(20,20,20,0.8) */
+#home .main,
+#reconnect .pane,
+#my-infos,
+#right-content,
+#buddy-list,
+#manager,
+#install {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#de141414,endColorstr=#de141414);
+}
+
+/* rgba(20,20,20,0.9) */
+.popup {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ed141414,endColorstr=#ed141414);
+}
+
+/* rgba(0,0,0,0.2) */
+#install-top .step {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#33000000,endColorstr=#33000000);
+}
+
+/* rgba(0,0,0,0.6) */
+.lock {
+       background: url(../img/others/lock.png) repeat !important;
+}
+
+/* rgba(0,0,0,0.8) */
+#page-engine .tooltip-subitem,
+.attach-subitem,
+.buddy-infos-subitem,
+.buddy-conf-subitem,
+.tools-content-subitem {
+       background: transparent;
+       filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#de000000,endColorstr=#de000000);
+}
+
+/* Fix a fieldset padding bug */
+legend {
+       margin-bottom: 5px !important;
+}
+
+/* Fix an opacity bug */
+a.finish.disabled {
+       filter: alpha(opacity = 20) !important;
+}
diff --git a/jappixmini/jappix/css/images.css b/jappixmini/jappix/css/images.css
new file mode 100644 (file)
index 0000000..2dfb756
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+
+Jappix - An open social platform
+This is the images CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+.body-images {
+       background-image: url(../img/sprites/background.png);
+       background-repeat: repeat;
+       background-color: #93c5fa;
+}
+
+.install-images {
+       background-image: url(../img/sprites/install.png);
+       background-repeat: no-repeat;
+}
+
+.home-images {
+       background-image: url(../img/sprites/home.png);
+       background-repeat: no-repeat;
+}
+
+.browsers-images {
+       background-image: url(../img/sprites/browsers.png);
+       background-repeat: no-repeat;
+}
+
+.buttons-images {
+       background-image: url(../img/sprites/buttons.png);
+       background-repeat: repeat-x;
+}
+
+.talk-images {
+       background-image: url(../img/sprites/talk.png);
+       background-repeat: no-repeat;
+}
+
+.smileys-images {
+       background-image: url(../img/sprites/smileys.png);
+       background-repeat: no-repeat;
+}
+
+.welcome-images {
+       background-image: url(../img/sprites/welcome.png);
+       background-repeat: no-repeat;
+}
+
+.me-images {
+       background-image: url(../img/sprites/me.png);
+       background-repeat: no-repeat;
+}
+
+.manager-images {
+       background-image: url(../img/sprites/manager.png);
+       background-repeat: no-repeat;
+}
+
+.mobile-images {
+       background-image: url(../img/sprites/mobile.png);
+       background-repeat: no-repeat;
+}
+
+.wait-small {
+       background-image: url(../img/wait/wait-small.gif);
+       background-repeat: no-repeat;
+       height: 16px;
+       width: 16px;
+}
+
+.wait-medium {
+       background-image: url(../img/wait/wait-medium.png);
+       background-repeat: no-repeat;
+       height: 24px;
+       width: 24px;
+}
+
+.wait-big {
+       background-image: url(../img/wait/wait-big.gif);
+       background-repeat: no-repeat;
+       height: 30px;
+       width: 30px;
+}
diff --git a/jappixmini/jappix/css/inbox.css b/jappixmini/jappix/css/inbox.css
new file mode 100644 (file)
index 0000000..1ef0588
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+
+Jappix - An open social platform
+This is the inbox CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+#inbox .content {
+       padding: 10px 0 10px 0;
+}
+
+#inbox .content p {
+       margin: 3px 10px;
+       text-align: justify;
+       font-size: 0.9em;
+}
+
+#inbox .inbox-results {
+       height: 310px;
+       width: 620px;
+       margin: -5px 0 0 10px;
+       padding: 6px 0 0 0;
+       overflow: auto;
+}
+
+#inbox .message-unread {
+       background-color: #E9F1FD;
+}
+
+#inbox .one-message {
+       font-size: 0.9em;
+       border-bottom: 1px #b2c7cb solid;
+}
+
+#inbox .message-head {
+       padding: 6px 0 7px 4px;
+       overflow: hidden;
+}
+
+#inbox .message-head:hover {
+       background-color: #e9f1fd;
+       cursor: pointer;
+}
+
+#inbox .message-head:active {
+       background-color: #f1f6fd;
+}
+
+#inbox .one-message.message-reading,
+#inbox .one-message.message-reading .message-head {
+       background-color: #f1f6fd;
+}
+
+#inbox .avatar-container {
+       float: left;
+       width: 40px;
+       height: 40px;
+       margin-right: 7px;
+       text-align: center;
+       background-repeat: no-repeat;
+}
+
+#inbox .avatar {
+       max-width: 40px;
+       max-height: 40px;
+}
+
+#inbox .message-jid,
+#inbox .message-subject {
+       float: left;
+       margin: 0 2px;
+       overflow: hidden;
+}
+
+#inbox .message-jid {
+       width: 165px;
+       font-weight: bold;
+}
+
+#inbox .message-subject {
+       width: 355px;
+}
+
+#inbox .message-truncated {
+       color: #42646b;
+       font-size: 0.8em;
+       margin: 23px 0 0 49px;
+}
+
+#inbox .message-body {
+       padding: 8px 5px 5px 5px;
+}
+
+#inbox .message-body a {
+       text-decoration: underline;
+}
+
+#inbox .message-meta {
+       margin-top: 6px;
+       padding: 3px 4px;
+       border-top: 1px #b2c7cb dotted;
+}
+
+#inbox .message-meta span.date {
+       color: #28474e;
+       font-size: 0.8em;
+       margin: 10px 0 0 4px;
+       float: left;
+}
+
+#inbox .message-meta a {
+       font-size: 0.98em;
+       margin: 5px;
+       float: right;
+       display: block;
+}
+
+#inbox .inbox-noresults {
+       font-weight: bold;
+       display: none;
+}
+
+#inbox .a-show-messages {
+       display: none;
+}
+
+#inbox .inbox-new {
+       display: none;
+       height: 300px;
+       width: 620px;
+       margin: -5px 0 0 10px;
+       padding: 16px 0 0 0;
+}
+
+#inbox .inbox-new-block {
+       border-top: 1px #686868 dotted;
+       padding-top: 9px;
+       min-height: 32px;
+       clear: both;
+}
+
+#inbox .inbox-new-text {
+       float: left;
+       width: 100px;
+}
+
+#inbox .inbox-new-textarea {
+       width: 460px;
+       height: 109px;
+       margin-bottom: 10px;
+       float: left;
+}
+
+#inbox .inbox-new input {
+       float: left;
+}
+
+#inbox .inbox-new-to ul {
+       width: 264px;
+       max-height: 168px;
+       font-size: 0.9em;
+       left: 120px;
+       top: 31px;
+}
+
+#inbox .inbox-new-to-input {
+       width: 260px;
+}
+
+#inbox .inbox-new-subject-input {
+       width: 380px;
+}
+
+#inbox .inbox-new-file a {
+       display: block;
+       float: left;
+}
+
+#inbox .inbox-new-file a.file {
+       font-size: 0.85em;
+       height: 16px;
+       max-width: 320px;
+       margin: 3px 0 15px 013px;
+       overflow: hidden;
+}
+
+#inbox .inbox-new-file a.one-button {
+       font-size: 0.85em;
+       margin: -2px 0 0 25px;
+}
+
+#inbox .inbox-new-send a {
+       font-size: 0.85em;
+       float: right;
+       display: block;
+}
diff --git a/jappixmini/jappix/css/install.css b/jappixmini/jappix/css/install.css
new file mode 100644 (file)
index 0000000..9dbde3f
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+
+Jappix - An open social platform
+This is the install CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 08/06/11
+
+*/
+
+body {
+       color: white;
+}
+
+#install {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.85);
+       width: 800px;
+       margin: 35px auto;
+       padding-bottom: 17px;
+       border-radius: 6px;
+       -moz-border-radius: 6px;
+       -webkit-border-radius: 6px;
+       box-shadow: 0 0 35px #5c5c5c;
+       -moz-box-shadow: 0 0 35px #5c5c5c;
+       -webkit-box-shadow: 0 0 35px #5c5c5c;
+}
+
+#install a {
+       color: black;
+       text-decoration: underline;
+}
+
+#install .clear {
+       clear: both;
+}
+
+#install fieldset {
+       border: 1px solid black;
+       margin: 22px 0 15px 0;
+       padding: 7px 2px 5px 2px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+#install legend {
+       font-size: 0.9em;
+       margin: 0 0 0 15px;
+       padding: 0 2px;
+       text-transform: uppercase;
+}
+
+#install label {
+       width: 200px;
+       display: block;
+       float: left;
+       clear: both;
+       margin: 0 0 9px 12px;
+}
+
+#install input {
+       float: left;
+       margin-bottom: 5px;
+}
+
+#install input[type=text],
+#install input[type=url],
+#install input[type=password] {
+       margin-top: -2px;
+       padding: 3px;
+       font-size: 0.95em;
+       min-width: 220px;
+}
+
+#install input.icon {
+       padding-left: 24px;
+       min-width: 199px;
+       max-height: 18px;
+}
+
+#install input.icon#user_name {
+       background-position: 4px -204px;
+}
+
+#install input.icon#user_password {
+       background-position: 4px -226px;
+}
+
+#install input.icon#user_repassword {
+       background-position: 4px -248px;
+}
+
+#install-top {
+       padding: 30px 45px;
+}
+
+#install-top .logo {
+       background-position: 0 0;
+       min-width: 88px;
+       height: 36px;
+       padding: 32px 0 0 66px;
+       font-size: 32px;
+       color: white;
+       text-transform: lowercase;
+       float: left;
+       text-shadow: 0 1px 1px black;
+}
+
+#install-top .step {
+       background-color: rgb(0,0,0);
+       background-color: rgba(0,0,0,0.2);
+       border: 2px solid white;
+       padding: 6px 21px;
+       font-size: 2.7em;
+       text-shadow: 0 1px 1px black;
+       float: right;
+       border-radius: 40px;
+       -moz-border-radius: 40px;
+       -webkit-border-radius: 40px;
+       box-shadow: 0 0 10px #202020;
+       -moz-box-shadow: 0 0 10px #202020;
+       -webkit-box-shadow: 0 0 10px #202020;
+}
+
+#install-top .step span {
+       font-size: 0.6em;
+}
+
+#install-content {
+       background: #e4eef9;
+       background: -moz-linear-gradient(top, #e4eef9, #d0e5fa);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#d0e5fa));
+       color: black;
+       font-size: 0.9em;
+       margin: 0 10px;
+       padding: 20px 24px;
+       min-height: 260px;
+       clear: both;
+       right: 10px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 20px #202020;
+       -moz-box-shadow: 0 0 20px #202020;
+       -webkit-box-shadow: 0 0 20px #202020;
+}
+
+#install-content h3 {
+       padding-left: 24px;
+       margin-bottom: 15px;
+}
+
+#install-content h3.start {
+       background-position: 0 -73px;
+}
+
+#install-content h3.storage {
+       background-position: 0 -95px;
+}
+
+#install-content h3.account {
+       background-position: 0 -117px;
+}
+
+#install-content h3.main {
+       background-position: 0 -139px;
+}
+
+#install-content h3.hosts {
+       background-position: 0 -161px;
+}
+
+#install-content h3.services {
+       background-position: 0 -183px;
+}
+
+#install-content p {
+       margin-bottom: 10px;
+}
+
+#install-content .info {
+       color: black;
+       border-width: 1px;
+       border-style: dashed;
+       padding: 6px 8px;
+       display: block;
+       text-decoration: none;
+}
+
+#install-content .info.smallspace {
+       margin: 14px 0 10px 0;
+}
+
+#install-content .info.bigspace {
+       margin: 35px 0 20px 0;
+}
+
+#install-content .info.first {
+       margin-top: 28px;
+}
+
+#install-content .info.last {
+       margin-bottom: 28px;
+}
+
+#install-content .info.neutral {
+       background-color: #f0f19d;
+       border-color: #b3ad4f;
+}
+
+#install-content a.info.neutral:hover,
+#install-content a.info.neutral:focus {
+       background-color: #eced96;
+}
+
+#install-content a.info.neutral:active {
+       background-color: #e9ea93;
+}
+
+#install-content .info.success {
+       background-color: #a8dca9;
+       border-color: #5e9f5f;
+}
+
+#install-content a.info.success:hover,
+#install-content a.info.success:focus {
+       background-color: #a0d5a1;
+}
+
+#install-content a.info.success:active {
+       background-color: #9ad09b;
+}
+
+#install-content .info.fail {
+       background-color: #f19d9d;
+       border-color: #b34f4f;
+}
+
+#install-content ol {
+       margin: 20px 30px;
+}
+
+#install-content ol li {
+       margin-bottom: 1px;
+}
+
+#install-buttons {
+       margin-top: 22px;
+}
+
+#install-buttons input {
+       border: 1px solid white;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+       color: white;
+       padding: 4px 8px;
+       margin-right: 20px;
+       text-shadow: 0 1px 1px black;
+       float: right;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 5px #202020;
+       -moz-box-shadow: 0 0 5px #202020;
+       -webkit-box-shadow: 0 0 5px #202020;
+}
+
+#install-buttons input:hover,
+#install-buttons input:focus {
+       cursor: pointer;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.2);
+       box-shadow: 0 0 15px #202020;
+       -moz-box-shadow: 0 0 15px #202020;
+       -webkit-box-shadow: 0 0 15px #202020;
+}
+
+#install-buttons input:active {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.3);
+}
diff --git a/jappixmini/jappix/css/integratebox.css b/jappixmini/jappix/css/integratebox.css
new file mode 100644 (file)
index 0000000..b5cb9c9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+
+Jappix - An open social platform
+This is the integratebox CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 06/11/10
+
+*/
+
+#integratebox .top {
+       height: 40px;
+}
+
+#integratebox .content {
+       text-align: center;
+       height: 385px;
+}
+
+#integratebox .one-media img {
+       max-height: 385px;
+       max-width: 640px;
+}
+
+#integratebox .one-media a img {
+       border: none;
+}
+
+#integratebox .one-media audio {
+       margin-top: 170px;
+}
diff --git a/jappixmini/jappix/css/jquery.datepicker.css b/jappixmini/jappix/css/jquery.datepicker.css
new file mode 100644 (file)
index 0000000..264cd54
--- /dev/null
@@ -0,0 +1,148 @@
+/*\r
+\r
+Jappix - An open social platform\r
+This is the datepicker CSS stylesheet\r
+\r
+-------------------------------------------------\r
+\r
+License: AGPL\r
+Author: Vanaryon\r
+Last revision: 28/12/10\r
+\r
+*/\r
+\r
+div.datepicker {\r
+       position: relative;\r
+       font-family: Arial, Helvetica, sans-serif;\r
+       font-size: 12px;\r
+       width: 196px;\r
+       height: 147px;\r
+       position: absolute;\r
+       cursor: default;\r
+       top: 0;\r
+       left: 0;\r
+       display: none;\r
+}\r
+\r
+.datepickerHidden {\r
+       display: none;\r
+}\r
+\r
+div.datepicker table {\r
+       border-collapse:collapse;\r
+}\r
+\r
+div.datepicker a {\r
+       text-decoration: none;\r
+       cursor: default;\r
+       outline: none;\r
+}\r
+\r
+div.datepicker table td {\r
+       text-align: right;\r
+       padding: 0;\r
+       margin: 0;\r
+}\r
+\r
+div.datepicker th {\r
+       text-align: center;\r
+       color: #47646a;\r
+       font-weight: normal;\r
+}\r
+\r
+div.datepicker tbody th {\r
+       text-align: left;\r
+}\r
+\r
+div.datepicker tbody a {\r
+       display: block;\r
+}\r
+\r
+.datepickerDays a {\r
+       width: 20px;\r
+       line-height: 16px;\r
+       height: 16px;\r
+       padding-right: 2px;\r
+}\r
+\r
+.datepickerYears a,\r
+.datepickerMonths a {\r
+       width: 44px;\r
+       line-height: 36px;\r
+       height: 36px;\r
+       text-align: center;\r
+}\r
+\r
+td.datepickerNotInMonth {\r
+       background: #c7d1d4;\r
+}\r
+\r
+tbody.datepickerDays td.datepickerSelected {\r
+       background: #b0bdc1;\r
+}\r
+\r
+tbody.datepickerYears td.datepickerSelected,\r
+tbody.datepickerMonths td.datepickerSelected {\r
+       background: #9daaae;\r
+}\r
+\r
+div.datepicker a:hover,\r
+div.datepicker a:focus {\r
+       color: #3d7682;\r
+}\r
+\r
+div.datepicker tbody th {\r
+       text-align: left;\r
+}\r
+\r
+.datepickerSpace div {\r
+       width: 20px;\r
+}\r
+\r
+.datepickerGoNext a,\r
+.datepickerGoPrev a,\r
+.datepickerMonth a {\r
+       text-align: center;\r
+       height: 20px;\r
+       line-height: 20px;\r
+}\r
+\r
+.datepickerGoNext a {\r
+       float: right;\r
+       width: 20px;\r
+}\r
+\r
+.datepickerGoPrev a {\r
+       float: left;\r
+       width: 20px;\r
+}\r
+\r
+table.datepickerViewDays tbody.datepickerMonths,\r
+table.datepickerViewDays tbody.datepickerYears {\r
+       display: none;\r
+}\r
+\r
+table.datepickerViewMonths tbody.datepickerDays,\r
+table.datepickerViewMonths tbody.datepickerYears,\r
+table.datepickerViewMonths tr.datepickerDoW {\r
+       display: none;\r
+}\r
+\r
+table.datepickerViewYears tbody.datepickerDays,\r
+table.datepickerViewYears tbody.datepickerMonths,\r
+table.datepickerViewYears tr.datepickerDoW {\r
+       display: none;\r
+}\r
+\r
+td.datepickerDisabled a,\r
+td.datepickerDisabled.datepickerNotInMonth a {\r
+       color: #333;\r
+}\r
+\r
+td.datepickerSpecial a {\r
+       background: #700;\r
+}\r
+\r
+td.datepickerSpecial.datepickerSelected a {\r
+       background: #a00;\r
+}\r
diff --git a/jappixmini/jappix/css/main.css b/jappixmini/jappix/css/main.css
new file mode 100644 (file)
index 0000000..6825481
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+
+Jappix - An open social platform
+This is the main CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 05/10/11
+
+*/
+
+* {
+       margin: 0;
+       padding: 0;
+}
+
+body {
+       font: normal 14.4px Helvetica, Verdana, sans-serif;
+       text-shadow: 0 0 5px white;
+}
+
+h1 {
+       margin-bottom: 15px;
+}
+
+a {
+       text-decoration: none;
+       color: black;
+       outline-style: none;
+}
+
+a:hover,
+a:focus {
+       cursor: pointer;
+       text-decoration: underline;
+}
+
+legend {
+       color: black;
+}
+
+input,
+textarea {
+       background-color: white;
+       border: 1px solid #636363;
+       font-size: 0.95em;
+       padding: 2px;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+       box-shadow: inset 0 3px 10px #dcdcdc;
+       -moz-box-shadow: inset 0 3px 10px #dcdcdc;
+       -webkit-box-shadow: inset 0 3px 10px #dcdcdc;
+}
+
+textarea {
+       font-size: 1.1em;
+}
+
+input:focus,
+input[type=submit]:hover,
+input[type=reset]:hover,
+textarea:focus {
+       border: 1px solid #e1a014;
+       box-shadow: inset 0 3px 10px #edd9bc;
+       -moz-box-shadow: inset 0 3px 10px #edd9bc;
+       -webkit-box-shadow: inset 0 3px 10px #edd9bc;
+}
+
+input[type=submit],
+input[type=reset] {
+       cursor: pointer;
+}
+
+input[type=submit]:active,
+input[type=reset]:active {
+       box-shadow: inset 0 3px 15px #e1a753;
+       -moz-box-shadow: inset 0 3px 15px #e1a753;
+       -webkit-box-shadow: inset 0 3px 15px #e1a753;
+}
+
+input[disabled],
+textarea[disabled] {
+       background-color: #f3f3f3;
+       border: 1px solid #989898;
+}
+
+input:placeholder {
+       color: #67787c !important;
+}
+
+input:-moz-placeholder {
+       color: #67787c !important;
+}
+
+input::-webkit-input-placeholder {
+       color: #67787c !important;
+}
+
+input.placeholder {
+       color: #67787c !important;
+}
+
+input[type=checkbox] {
+       margin-top: 2px;
+}
+
+input[type=checkbox],
+input[type=radio] {
+       background: transparent none !important;
+       border: 0 none !important;
+}
+
+.please-complete,
+.please-complete:hover,
+.please-complete:focus {
+       border: 1px #ac2525 solid !important;
+       box-shadow: inset 0 3px 10px #f39c9c !important;
+       -moz-box-shadow: inset 0 3px 10px #f39c9c !important;
+       -webkit-box-shadow: inset 0 3px 10px #f39c9c !important;
+}
+
+.hidden {
+       display: none !important;
+}
+
+.clear {
+       clear: both !important;
+}
diff --git a/jappixmini/jappix/css/manager.css b/jappixmini/jappix/css/manager.css
new file mode 100644 (file)
index 0000000..c1dd358
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+
+Jappix - An open social platform
+This is the manager CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 31/08/11
+
+*/
+
+#manager {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.85);
+       width: 945px;
+       margin: 0 auto 25px;
+       padding-bottom: 17px;
+       border-bottom-left-radius: 4px;
+       border-bottom-right-radius: 4px;
+       -moz-border-radius-bottomleft: 4px;
+       -moz-border-radius-bottomright: 4px;
+       -webkit-border-bottom-left-radius: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+       box-shadow: 0 0 35px #5c5c5c;
+       -moz-box-shadow: 0 0 35px #5c5c5c;
+       -webkit-box-shadow: 0 0 35px #5c5c5c;
+}
+
+#manager a {
+       color: black;
+       text-decoration: underline;
+}
+
+#manager .clear {
+       clear: both;
+}
+
+#manager fieldset {
+       border: 1px solid black;
+       margin: 22px 0 15px 0;
+       padding: 7px 2px 5px 2px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+#manager legend {
+       font-size: 0.9em;
+       margin: 0 0 0 15px;
+       padding: 0 2px;
+       text-transform: uppercase;
+}
+
+#manager label {
+       width: 200px;
+       display: block;
+       float: left;
+       clear: both;
+       margin: 0 0 9px 12px;
+}
+
+#manager label.master {
+       text-decoration: underline;
+}
+
+#manager input,
+#manager select {
+       float: left;
+       margin-bottom: 5px;
+}
+
+#manager input[type=radio] {
+       margin: 2px 8px 5px 0;
+}
+
+#manager input[type=text],
+#manager input[type=url],
+#manager input[type=password],
+#manager select {
+       margin-top: -2px;
+       font-size: 0.95em;
+}
+
+#manager input[type=text],
+#manager input[type=url],
+#manager input[type=password] {
+       padding: 3px;
+       min-width: 220px;
+}
+
+#manager input.icon {
+       padding-left: 24px;
+       min-width: 199px;
+       max-height: 18px;
+}
+
+#manager input.icon#admin_name {
+       background-position: 4px -510px;
+}
+
+#manager input.icon#admin_password,
+#manager input.icon#user_repassword {
+       background-position: 4px -532px;
+}
+
+#manager input.icon#user_name,
+#manager input.icon#music_artist {
+       background-position: 4px -554px;
+}
+
+#manager input.icon#user_password {
+       background-position: 4px -576px;
+}
+
+#manager input.icon#music_title {
+       background-position: 4px -598px;
+}
+
+#manager input.icon#music_album {
+       background-position: 4px -620px;
+}
+
+#manager input.icon#background_image_color,
+#manager input.icon#background_color_color {
+       background-position: 4px -641px;
+}
+
+#manager select {
+       min-width: 160px;
+       max-width: 230px;
+}
+
+#manager-top {
+       padding: 25px 45px 30px;
+}
+
+#manager-top .logo {
+       background-position: 0 0;
+       min-width: 89px;
+       height: 40px;
+       padding: 28px 0 0 65px;
+       font-size: 32px;
+       color: white;
+       text-transform: lowercase;
+       float: left;
+       text-shadow: 0 1px 1px black;
+}
+
+#manager-top .meta {
+       background-color: #e0eaec;
+       font-size: 0.9em;
+       padding: 12px 7px 12px 14px;
+       float: right;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 10px #202020;
+       -moz-box-shadow: 0 0 10px #202020;
+       -webkit-box-shadow: 0 0 10px #202020;
+}
+
+#manager-top .meta span {
+       margin-right: 10px;
+       color: black;
+}
+
+#manager-top .meta a {
+       background-color: #f1f6fd;
+       border: 1px solid #b9cbcf;
+       color: #224249;
+       padding: 4px 8px 4px 21px;
+       margin-left: 2px;
+       text-decoration: none;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+#manager-top .meta a:hover,
+#manager-top .meta a:focus {
+       border: 1px solid #95b1b7;
+}
+
+#manager-top .meta a:active {
+       border: 1px solid #77989f;
+}
+
+#manager-top .meta a.logout {
+       background-position: 3px -69px;
+}
+
+#manager-top .meta a.close {
+       background-position: 3px -90px;
+}
+
+#manager-tabs {
+       margin-left: 12px;
+}
+
+#manager-tabs a {
+       background-color: #d9e7ea;
+       color: #204249;
+       width: 107px;
+       height: 17px;
+       padding: 4px 4px 4px 16px;
+       margin-left: 4px;
+       font-size: 0.94em;
+       text-decoration: none;
+       overflow: hidden;
+       float: left;
+       border-top-right-radius: 3px;
+       border-top-left-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -moz-border-radius-topleft: 3px;
+       -webkit-border-top-right-radius: 3px;
+       -webkit-border-top-left-radius: 3px;
+}
+
+#manager-tabs a:hover,
+#manager-tabs a:focus {
+       background-color: #cedee1;
+       text-decoration: none;
+}
+
+#manager-tabs a:active {
+       background-color: #c3d3d7;
+       text-decoration: none;
+}
+
+#manager-tabs a.tab-active {
+       background-color: #e4eef9 !important;
+}
+
+#manager-content {
+       background: #e4eef9;
+       background: -moz-linear-gradient(top, #e4eef9, #d0e5fa);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#d0e5fa));
+       color: black;
+       font-size: 0.9em;
+       margin: 0 10px;
+       padding: 20px 24px;
+       min-height: 260px;
+       clear: both;
+       right: 10px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 20px #202020;
+       -moz-box-shadow: 0 0 20px #202020;
+       -webkit-box-shadow: 0 0 20px #202020;
+}
+
+#manager-content h3 {
+       padding-left: 24px;
+       margin-bottom: 15px;
+}
+
+#manager-content h3.login {
+       background-position: 0 -466px;
+}
+
+#manager-content h3.statistics {
+       background-position: 0 -203px;
+}
+
+#manager-content h3.configuration {
+       background-position: 0 -224px;
+}
+
+#manager-content h3.hosts {
+       background-position: 0 -246px;
+}
+
+#manager-content h3.storage {
+       background-position: 0 -268px;
+}
+
+#manager-content h3.design {
+       background-position: 0 -290px;
+}
+
+#manager-content h3.users {
+       background-position: 0 -312px;
+}
+
+#manager-content h3.updates {
+       background-position: 0 -334px;
+}
+
+#manager-content h4 {
+       border-top: 1px dotted black;
+       padding-top: 5px;
+       margin: 20px 0 14px;
+       clear: both;
+}
+
+#manager-content ul,
+#manager-content ol {
+       width: 380px;
+       margin: 8px 0 20px 18px;
+}
+
+#manager-content li {
+       margin-bottom: 3px;
+}
+
+#manager-content li.total {
+       margin-bottom: 14px;
+}
+
+#manager-content li b {
+       width: 190px;
+       float: left;
+}
+
+#manager-content li span {
+       margin-left: 10px;
+       float: left;
+}
+
+#manager-content ul.stats,
+#manager-content ol.stats {
+       float: left;
+}
+
+#manager-content object.stats {
+       border: 1px dotted #bed4d9;
+       width: 450px;
+       height: 270px;
+       margin-bottom: 20px;
+       float: right;
+}
+
+#manager-content p,
+#manager-content div {
+       margin-bottom: 10px;
+}
+
+#manager-content .info {
+       color: black;
+       border-width: 1px;
+       border-style: dashed;
+       padding: 6px 8px;
+       display: block;
+       text-decoration: none;
+}
+
+#manager-content .info.bottomspace {
+       margin-bottom: 16px;
+}
+
+#manager-content .info.smallspace {
+       margin: 14px 0 10px 0;
+}
+
+#manager-content .info.bigspace {
+       margin: 35px 0 20px 0;
+}
+
+#manager-content .info.neutral {
+       background-color: #f0f19d;
+       border-color: #b3ad4f;
+}
+
+#manager-content a.info.neutral:hover,
+#manager-content a.info.neutral:focus {
+       background-color: #eced96;
+}
+
+#manager-content a.info.neutral:active {
+       background-color: #e9ea93;
+}
+
+#manager-content .info.success {
+       background-color: #a8dca9;
+       border-color: #5e9f5f;
+}
+
+#manager-content a.info.success:hover,
+#manager-content a.info.success:focus {
+       background-color: #a0d5a1;
+}
+
+#manager-content a.info.success:active {
+       background-color: #9ad09b;
+}
+
+#manager-content .info.fail {
+       background-color: #f19d9d;
+       border-color: #b34f4f;
+}
+
+#manager-content a.info.fail:hover,
+#manager-content a.info.fail:focus {
+       background-color: #ea9595;
+}
+
+#manager-content a.info.fail:active {
+       background-color: #e59090;
+}
+
+#manager-content .browse {
+       margin: 2px 0 6px;
+       max-height: 243px;
+       overflow: auto;
+}
+
+#manager-content .browse .one-browse {
+       padding: 5px 10px 5px 34px;
+       height: 17px;
+}
+
+#manager-content .browse .user {
+       background-position: 9px -111px;
+}
+
+#manager-content .browse .other {
+       background-position: 9px -133px;
+}
+
+#manager-content .browse .folder {
+       background-position: 9px -178px;
+}
+
+#manager-content .browse .audio {
+       background-position: 9px -154px;
+}
+
+#manager-content .browse .alert {
+       background-position: 9px -353px;
+}
+
+#manager-content .browse .image {
+       background-position: 9px -374px;
+}
+
+#manager-content .browse .video {
+       background-position: 9px -397px;
+}
+
+#manager-content .browse .document {
+       background-position: 9px -418px;
+}
+
+#manager-content .browse .package {
+       background-position: 9px -441px;
+}
+
+#manager-content .browse .previous {
+       background-position: 9px -485px;
+       margin-bottom: 4px;
+}
+
+#manager-content .browse div {
+       margin: 0;
+}
+
+#manager-content .browse input {
+       float: right;
+       margin: 1px 0;
+}
+
+#manager-content .browse .odd {
+       background-color: #e9f1fd;
+}
+
+#manager-content .browse .even {
+       background-color: #f1f6fd;
+}
+
+#manager-content .sub {
+       border-left: 1px solid black;
+       margin: 5px 0 20px 22px;
+       padding-left: 12px;
+       clear: both;
+}
+
+#manager span.logo_links a {
+       width: 16px;
+       height: 16px;
+       margin-right: 6px;
+       float: left;
+}
+
+#manager span.logo_links a.remove {
+       background-position: 0 -688px;
+}
+
+#manager span.logo_links a.view {
+       background-position: 0 -666px;
+}
+
+#manager-content .clear {
+       margin: 0;
+}
+
+#manager-content textarea.notice-text {
+       height: 70px;
+       width: 600px;
+       margin-left: 4px;
+       padding: 5px;
+       font-size: 1.2em;
+}
+
+#manager-buttons {
+       margin-top: 22px;
+}
+
+#manager-buttons input {
+       border: 1px solid white;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+       color: white;
+       padding: 4px 8px;
+       margin-left: -12px;
+       margin-right: 20px;
+       font-size: 1em;
+       text-shadow: 0 1px 1px black;
+       float: right;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 5px #202020;
+       -moz-box-shadow: 0 0 5px #202020;
+       -webkit-box-shadow: 0 0 5px #202020;
+}
+
+#manager-buttons input:hover,
+#manager-buttons input:focus {
+       cursor: pointer;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.2);
+       box-shadow: 0 0 15px #202020;
+       -moz-box-shadow: 0 0 15px #202020;
+       -webkit-box-shadow: 0 0 15px #202020;
+}
+
+#manager-buttons input:active {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.3);
+}
diff --git a/jappixmini/jappix/css/me.css b/jappixmini/jappix/css/me.css
new file mode 100644 (file)
index 0000000..2ff74fb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+
+Jappix - An open social platform
+This is the Jappix Me tool CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+#me .content {
+       padding: 10px 0;
+}
+
+#me .logo {
+       background-position: 0 0;
+       width: 300px;
+       height: 61px;
+       margin: 20px auto 0 auto;
+       display: block;
+}
+
+#me .infos {
+       margin-top: 30px;
+}
+
+#me .infos p {
+       margin-top: 8px;
+}
+
+#me .infos p.infos-title {
+       margin-top: 0;
+}
+
+#me .infos a {
+       text-decoration: underline;
+}
+
+#me a.go {
+       text-align: center;
+       font-weight: bold;
+       width: 300px;
+       margin: 30px auto 0 auto;
+       padding: 8px 12px;
+       display: block;
+}
\ No newline at end of file
diff --git a/jappixmini/jappix/css/mini-ie.css b/jappixmini/jappix/css/mini-ie.css
new file mode 100644 (file)
index 0000000..d8f4b90
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+
+Jappix - An open social platform
+This is the Jappix Mini legacy IE CSS stylesheet
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 20/03/11
+
+*/
+
+#jappix_mini {
+       width: expression(document.documentElement.clientWidth - 150 + 'px') !important;
+       position: absolute !important;
+       bottom: auto !important;
+       right: auto !important;
+       top: expression(((document.documentElement.clientHeight - this.offsetHeight) + (ignoreMiniTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)) + 'px') !important;
+       left: expression((150 + this.offsetWidth - (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth) + (ignoreMiniLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft)) + 'px') !important;
+}
+
+#jappix_mini .jm_images {
+       background-image: url(../img/sprites/mini.gif) !important;
+}
+
+#jappix_mini .jm_images_animate {
+       background-image: url(../img/sprites/animate.gif) !important;
+}
+
+#jappix_mini a.jm_button {
+       width: 1px !important;
+}
+
+#jappix_mini div.jm_roster {
+       right: -1px !important;
+       bottom: 23px !important;
+}
+
+#jappix_mini div.jm_roster div.jm_buddies {
+       height: expression(this.scrollHeight > (document.documentElement.clientHeight - 70) ? (document.documentElement.clientHeight - 70) + 'px' : 'auto') !important;
+}
+
+#jappix_mini a.jm_pane {
+       height: 12px !important;
+       overflow-y: hidden !important;
+}
+
+#jappix_mini a.jm_button.jm_clicked {
+       background-image: none !important;
+}
+
+#jappix_mini div.jm_conversations a.jm_clicked {
+       border-right: none !important;
+       padding: 7px 6px 6px 6px !important;
+}
+
+#jappix_mini div.jm_chat-content {
+       bottom: 23px !important;
+       right: -2px !important;
+}
+
+#jappix_popup {
+       height: expression(document.documentElement.clientHeight + 'px') !important;
+       width: expression(document.documentElement.clientWidth + 'px') !important;
+       position: absolute !important;
+       top: expression(((ignorePopupTop = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)) + 'px') !important;
+       left: expression(((ignorePopupLeft = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft)) + 'px') !important;
+}
+
+#jappix_popup div.jm_prompt {
+       position: absolute !important;
+}
diff --git a/jappixmini/jappix/css/mini.css b/jappixmini/jappix/css/mini.css
new file mode 100644 (file)
index 0000000..6d77540
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+
+Jappix - An open social platform
+This is the Jappix Mini CSS stylesheet
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Julien
+Last revision: 16/01/12
+
+*/
+
+#jappix_mini,
+#jappix_popup {
+       font: normal 11px helvetica, "Lucida Grande", "Lucida Sans", "Lucida Sans Unicode", Arial, sans-serif;
+}
+
+#jappix_mini {
+       margin-left: 130px;
+       position: fixed;
+       bottom: 0;
+       right: 20px;
+       z-index: 999;
+}
+
+#jappix_mini *,
+#jappix_popup * {
+       border: none;
+       color: black;
+       width: auto;
+       height: auto;
+       margin: 0;
+       padding: 0;
+       overflow: visible;
+       font-size: 11px;
+       text-align: left;
+       text-transform: none;
+       text-shadow: none;
+       opacity: 1.0;
+       border-radius: 0;
+       -moz-border-radius: 0;
+       -webkit-border-radius: 0;
+       box-shadow: none;
+       -moz-box-shadow: none;
+       -webkit-box-shadow: none;
+}
+
+#jappix_mini .jm_images {
+       background-image: url(../img/sprites/mini.png);
+       background-repeat: no-repeat;
+}
+
+#jappix_mini .jm_images_animate {
+       background-image: url(../img/sprites/animate.png);
+       background-repeat: no-repeat;
+}
+
+#jappix_mini a {
+       text-decoration: none;
+       cursor: pointer;
+}
+
+#jappix_mini a:hover {
+       cursor: pointer;
+}
+
+#jappix_mini div.jm_position {
+       float: right;
+}
+
+#jappix_mini a.jm_pane {
+       background-color: #f4f4f4;
+       background-position: 0 -100px;
+       background-repeat: repeat-x;
+       border-color: #999999;
+       border-style: solid;
+       border-width: 1px 1px 0 1px;
+       font-weight: bold;
+       outline-style: none;
+       display: block;
+       padding: 6px;
+       height: 13px;
+}
+
+#jappix_mini a.jm_pane:hover {
+       background: white;
+}
+
+#jappix_mini a.jm_pane:hover,
+#jappix_mini a.jm_pane:focus {
+       border-color: #666666;
+}
+
+#jappix_mini div.jm_starter,
+#jappix_mini div.jm_conversations,
+#jappix_mini div.jm_conversation {
+       float: left;
+       position: relative;
+}
+
+#jappix_mini div.jm_conversation {
+       width: 153px;
+}
+
+#jappix_mini a.jm_chat-tab {
+       border-width: 1px 0 0 1px;
+       width: 140px;
+       float: right;
+       overflow: hidden;
+}
+
+#jappix_mini a.jm_chat-tab.jm_clicked {
+       background: white;
+       position: relative;
+       border-top: none;
+       border-left: 1px solid #999999;
+       padding-top: 7px;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify {
+       position: absolute;
+       top: 6px;
+       right: 9px;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify span {
+       float: left;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_left {
+       background-position: 0 -360px;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_right {
+       background-position: -7px -360px;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_left,
+#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_right {
+       height: 16px;
+       width: 7px;
+}
+
+#jappix_mini a.jm_chat-tab span.jm_notify span.jm_notify_middle {
+       background-color: #c60505;
+       color: white;
+       font-size: 0.85em;
+       height: 14px;
+       padding-top: 2px;
+}
+
+#jappix_mini div.jm_conversation.jm_type_groupchat span.jm_name {
+       margin-left: 4px;
+}
+
+#jappix_mini div.jm_chat-content {
+       background-color: white;
+       border: 1px solid #999999;
+       height: 300px;
+       width: 260px;
+       position: absolute;
+       right: -1px;
+       bottom: 25px;
+       display: none;
+}
+
+#jappix_mini div.jm_actions {
+       background-color: #565d5e;
+       border-bottom: 1px solid #3a3a3a;
+       height: 14px;
+       padding: 4px 6px;
+       font-weight: bold;
+       overflow: hidden;
+}
+
+#jappix_mini div.jm_actions span.jm_nick {
+       color: white;
+       height: 16px;
+       width: 225px;
+       overflow: hidden;
+       float: left;
+}
+
+#jappix_mini div.jm_actions a.jm_one-action {
+       background-color: #727879;
+       margin: 0 -2px 0 5px;
+       height: 15px;
+       width: 15px;
+       outline-style: none;
+       float: right;
+}
+
+#jappix_mini div.jm_actions a.jm_one-action:hover,
+#jappix_mini div.jm_actions a.jm_one-action:focus {
+       background-color: #7f8788;
+}
+
+#jappix_mini div.jm_actions a.jm_one-action:active {
+       background-color: #8c9293;
+}
+
+#jappix_mini div.jm_actions a.jm_logo {
+       background-position: 7px 2px;
+       width: 81px;
+       height: 22px;
+       margin: -4px 0 0 -2px;
+       outline-style: none;
+       float: left;
+}
+
+#jappix_mini div.jm_actions a.jm_logo:hover,
+#jappix_mini div.jm_actions a.jm_logo:focus {
+       background-color: #636a6b;
+}
+
+#jappix_mini div.jm_actions a.jm_logo:active {
+       background-color: #707677;
+}
+
+#jappix_mini div.jm_actions a.jm_close {
+       background-position: 1px -341px;
+}
+
+#jappix_mini div.jm_actions a.jm_join {
+       background-position: 0 -327px;
+}
+
+#jappix_mini div.jm_received-messages {
+       background-color: white;
+       padding: 5px 0 4px;
+       height: 242px;
+       overflow: auto;
+}
+
+#jappix_mini div.jm_received-messages p {
+       margin: 3px 0;
+       word-wrap: break-word;
+}
+
+#jappix_mini div.jm_received-messages p,
+#jappix_mini div.jm_received-messages a {
+       color: black !important;
+}
+
+#jappix_mini div.jm_received-messages div.jm_group {
+       margin: 2px 6px 9px 6px;
+       padding-bottom: 8px;
+       border-bottom: 1px solid #eaeaea;
+}
+
+#jappix_mini div.jm_received-messages div.jm_system-message p,
+#jappix_mini div.jm_received-messages div.jm_system-message a {
+       color: #053805 !important;
+       font-style: italic !important;
+}
+
+#jappix_mini div.jm_received-messages p a {
+       text-decoration: underline;
+}
+
+#jappix_mini div.jm_received-messages b {
+       margin-bottom: 3px;
+       display: block;
+}
+
+#jappix_mini div.jm_received-messages b.jm_me {
+       color: #123a5c;
+}
+
+#jappix_mini div.jm_received-messages b.jm_him {
+       color: #801e1e;
+}
+
+#jappix_mini div.jm_received-messages span.jm_date {
+       font-size: 0.8em;
+       float: right;
+       display: none;
+}
+
+#jappix_mini div.jm_received-messages div.jm_group:hover span.jm_date {
+       display: block;
+}
+
+#jappix_mini input.jm_send-messages {
+       background-color: white;
+       border-color: #999999;
+       border-style: solid;
+       border-width: 1px 0 0 0;
+       padding: 5px;
+       width: 250px;
+       min-height: 14px;
+}
+
+#jappix_mini div.jm_disabled div.jm_chat-content,
+#jappix_mini div.jm_disabled input.jm_send-messages,
+#jappix_mini div.jm_disabled a.jm_pane {
+       background: #f3f3f3 !important;
+}
+
+#jappix_mini div.jm_disabled input.jm_send-messages {
+       color: #9d9d9d;
+}
+
+#jappix_mini div.jm_roster {
+       background-color: white;
+       border: 1px solid #999999;
+       width: 160px;
+       position: absolute;
+       right: 0;
+       bottom: 25px;
+       display: none;
+}
+
+#jappix_mini div.jm_roster div.jm_buddies {
+       width: 100%;
+       max-height: 300px;
+       padding: 5px 0;
+       overflow: auto;
+}
+
+#jappix_mini div.jm_roster div.jm_grouped {
+       margin: 2px 0;
+}
+
+#jappix_mini div.jm_roster div.jm_grouped div.jm_name {
+       margin-bottom: 2px;
+       padding: 4px 8px 0;
+       font-weight: bold;
+}
+
+#jappix_mini a.jm_friend {
+       border-color: white;
+       border-style: solid;
+       border-width: 1px 0;
+       outline-style: none;
+       padding: 6px;
+       display: block;
+}
+
+#jappix_mini a.jm_friend.jm_offline {
+       display: none;
+}
+
+#jappix_mini a.jm_friend:hover,
+#jappix_mini a.jm_friend:focus {
+       background-color: #888888;
+       border-color: #494949;
+       color: white;
+}
+
+#jappix_mini a.jm_friend:hover span.jm_presence,
+#jappix_mini a.jm_friend:focus span.jm_presence {
+       background-position: 0 -84px;
+}
+
+#jappix_mini a.jm_button {
+       padding: 6px 10px;
+       position: relative;
+       z-index: 1;
+}
+
+#jappix_mini a.jm_button.jm_clicked {
+       background: white;
+       border-top: none;
+       border-left: 1px solid #999999;
+       border-right: 1px solid #999999;
+       padding: 7px 10px 6px 10px;
+}
+
+#jappix_mini span.jm_animate {
+       background-position: 0 0;
+       width: 111px;
+       height: 102px;
+       position: absolute;
+       top: -100px;
+       left: -74px;
+       z-index: 1;
+       display: block;
+}
+
+#jappix_mini span.jm_counter {
+       background-position: 0 -288px;
+       color: #333333;
+       height: 16px;
+       padding-left: 25px;
+       display: block;
+}
+
+#jappix_mini span.jm_counter.jm_error {
+       background-position: 0 -305px;
+}
+
+#jappix_mini span.jm_presence {
+       display: block;
+       height: 16px;
+       width: 16px;
+       margin-right: 4px;
+       float: left;
+}
+
+#jappix_mini span.jm_name {
+       color: #272727;
+       height: 14px;
+       width: 105px;
+       overflow: hidden;
+       float: left;
+}
+
+#jappix_mini .jm_available,
+#jappix_mini .jm_chat {
+       background-position: 0 -20px;
+}
+
+#jappix_mini .jm_away {
+       background-position: 0 -36px;
+}
+
+#jappix_mini .jm_xa,
+#jappix_mini .jm_dnd {
+       background-position: 0 -52px;
+}
+
+#jappix_mini .jm_unavailable {
+       background-position: 0 -68px;
+}
+
+#jappix_mini .jm_smiley {
+       border: 0 none;
+       height: 16px;
+       width: 16px;
+       vertical-align: bottom;
+}
+
+#jappix_mini .jm_smiley-wink {
+       background-position: 0 -148px;
+}
+
+#jappix_mini .jm_smiley-waii {
+       background-position: 0 -164px;
+}
+
+#jappix_mini .jm_smiley-unhappy {
+       background-position: 0 -180px;
+}
+
+#jappix_mini .jm_smiley-tongue {
+       background-position: 0 -196px;
+}
+
+#jappix_mini .jm_smiley-surprised {
+       background-position: 0 -212px;
+}
+
+#jappix_mini .jm_smiley-smile {
+       background-position: 0 -228px;
+}
+
+#jappix_mini .jm_smiley-happy {
+       background-position: 0 -244px;
+}
+
+#jappix_mini .jm_smiley-grin {
+       background-position: 0 -260px;
+}
+
+#jappix_popup {
+       background: url(../img/others/blank.gif) repeat;
+       position: fixed;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       z-index: 999;
+}
+
+#jappix_popup div.jm_prompt {
+       background-color: #565d5e;
+       border: 1px solid #3a3a3a;
+       width: 346px;
+       position: fixed;
+       top: 50%;
+       left: 50%;
+       margin-left: -175px;
+       padding: 16px 2px 2px 2px;
+       border-top-right-radius: 4px;
+       border-top-left-radius: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       -webkit-border-top-right-radius: 4px;
+       -webkit-border-top-left-radius: 4px;
+       box-shadow: 0 0 35px #232323;
+       -moz-box-shadow: 0 0 35px #232323;
+       -webkit-box-shadow: 0 0 35px #232323;
+}
+
+#jappix_popup div.jm_prompt form {
+       background-color: white;
+       border: 1px solid #3a3a3a;
+       width: 332px;
+       padding: 6px;
+}
+
+#jappix_popup div.jm_prompt form input {
+       background-color: #f9f9f9;
+       border: 1px solid #666666;
+       font-size: 1.1em;
+       padding: 1px 2px;
+}
+
+#jappix_popup div.jm_prompt form input:hover,
+#jappix_popup div.jm_prompt form input:focus {
+       border: 1px solid #202020;
+}
+
+#jappix_popup div.jm_prompt form input.jm_text {
+       width: 326px;
+       margin: 6px 0;
+       display: block;
+}
+
+#jappix_popup div.jm_prompt form input.jm_submit {
+       text-align: center;
+       margin-left: 3px;
+       float: right;
+}
+
+#jappix_popup div.jm_prompt form input.jm_submit:hover,
+#jappix_popup div.jm_prompt form input.jm_submit:focus {
+       background-color: #f3f3f3;
+       cursor: pointer;
+}
+
+#jappix_popup div.jm_prompt form input.jm_submit:active {
+       background-color: #e8e8e8;
+}
+
+#jappix_popup div.jm_prompt div.jm_clear {
+       clear: both;
+}
diff --git a/jappixmini/jappix/css/mobile.css b/jappixmini/jappix/css/mobile.css
new file mode 100644 (file)
index 0000000..ed44cc0
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+
+Jappix - An open social platform
+This is the Jappix Mobile CSS stylesheet
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 05/10/11
+
+*/
+
+/* BEGIN GENERAL STYLE */
+
+* {
+       margin: 0;
+       padding: 0;
+}
+
+body {
+       font: normal 14.4px Helvetica, Verdana, sans-serif;
+       background-color: #dcdcdc;
+       margin: 0 auto;
+       text-align: center;
+       min-width: 200px;
+       min-height: 260px;
+}
+
+a {
+       color: black;
+}
+
+/* END GENERAL STYLE */
+
+/* BEGIN HEADER STYLE */
+
+.header {
+       background-color: #2d2d2d;
+       border-bottom: 1px solid #6d6d6d;
+       color: #405964;
+       padding: 6px 0;
+       height: 30px;
+}
+
+.header div {
+       background-position: 0 0;
+       width: 83px;
+       height: 30px;
+}
+
+/* END HEADER STYLE */
+
+/* BEGIN HOME STYLE */
+
+#home .header div {
+       margin: 0 auto;
+}
+
+#home .notification {
+       padding: 2px;
+       margin-top: -1px;
+}
+
+#noscript {
+       background: #86a2ff;
+       border-bottom: 1px solid #5890d6;
+       color: #1e4b82;
+}
+
+#error {
+       background: #ff8686;
+       border-bottom: 1px solid #d65858;
+       color: #821e1e;
+       display: none;
+}
+
+#info {
+       background: #f3eba7;
+       border-bottom: 1px solid #d9d085;
+       color: #5e5616;
+       display: none;
+}
+
+#home .login {
+       padding: 8px 0;
+       margin: 30px 0 30px 0;
+}
+
+#home .login input {
+       margin-top: 5px;
+       padding: 2px;
+}
+
+#home .login input.xid,
+#home .login input.password {
+       display: block;
+       margin: 4px auto;
+       font-size: 0.85em;
+       padding: 4px;
+       background-color: white;
+       border: 1px solid #636363;
+       width: 150px;
+       padding-left: 24px;
+}
+
+#home .login input.xid {
+       background-position: 4px -30px;
+}
+
+#home .login input.password {
+       background-position: 4px -53px;
+}
+
+#home .login label {
+       margin-bottom: 12px;
+       display: block;
+}
+
+#home .login label input {
+       margin-right: 4px;
+}
+
+#home a {
+       font-size: 0.8em;
+}
+
+/* END HOME STYLE */
+
+/* BEGIN TALK STYLE */
+
+#talk .header div,
+#chat .header div {
+       float: left;
+       margin-left: 7px;
+}
+
+#talk .header button,
+#chat .header button {
+       float: right;
+       margin-right: 7px;
+       padding: 2px;
+}
+
+#talk a.one-buddy {
+       display: none;
+       background-color: #87a5ab;
+       border-bottom: 1px solid #5b8088;
+       text-shadow: 1px 1px 1px #5b8088;
+       text-decoration: none;
+       color: white;
+       outline-style: none;
+       padding: 10px 0;
+}
+
+#talk a.one-buddy:hover {
+       cursor: pointer;
+}
+
+#talk a.available,
+#talk a.chat {
+       background-color: #83b187;
+       border-bottom: 1px solid #4d8252;
+       text-shadow: 1px 1px 1px #4d8252;
+}
+
+#talk a.available:hover,
+#talk a.chat:hover,
+#talk a.available:focus,
+#talk a.chat:focus {
+       background-color: #89c68e;
+}
+
+#talk a.available:active,
+#talk a.chat:active {
+       background-color: #90d496;
+}
+
+#talk a.away {
+       background-color: #e0be7b;
+       border-bottom: 1px solid #ae8941;
+       text-shadow: 1px 1px 1px #ae8941;
+}
+
+#talk a.away:hover,
+#talk a.away:focus {
+       background-color: #eac784;
+}
+
+#talk a.away:active {
+       background-color: #f3d294;
+}
+
+#talk a.xa,
+#talk a.dnd {
+       background-color: #db8989;
+       border-bottom: 1px solid #a24343;
+       text-shadow: 1px 1px 1px #a24343;
+}
+
+#talk a.xa:hover,
+#talk a.dnd:hover,
+#talk a.xa:focus,
+#talk a.dnd:focus {
+       background-color: #e89797;
+}
+
+#talk a.xa:active,
+#talk a.dnd:active {
+       background-color: #ef9f9f;
+}
+
+/* END TALK STYLE */
+
+/* BEGIN CHAT STYLE */
+
+#chat {
+       display: none;
+}
+
+#chat .one-chat,
+#chat .one-chat p,
+#chat .one-chat div,
+#chat .one-chat input {
+       position: absolute;
+       bottom: 0;
+       right: 0;
+}
+
+#chat .one-chat {
+       top: 43px;
+       left: 0;
+}
+
+#chat .one-chat p {
+       background-color: #87a5ab;
+       border-bottom: 1px solid #5b8088;
+       text-shadow: 1px 1px 1px #5b8088;
+       color: white;
+       top: 0;
+       left: 0;
+       height: 18px;
+       padding: 2px 0;
+       font-size: 0.9em;
+}
+
+#chat .one-chat div {
+       border-bottom: 1px solid #cbcbcb;
+       top: 23px;
+       left: 0;
+       bottom: 25px;
+       overflow: auto;
+       text-align: left;
+}
+
+#chat .one-chat span {
+       display: block;
+       font-size: 0.85em;
+       margin: 4px 6px;
+       word-wrap: break-word;
+}
+
+#chat .one-chat b {
+       margin-right: 3px;
+}
+
+#chat .one-chat b.me {
+       color: #123a5c;
+}
+
+#chat .one-chat b.him {
+       color: #801e1e;
+}
+
+#chat .one-chat input {
+       background-color: white;
+       bottom: 0;
+       height: 25px;
+       width: 100%;
+       border: none;
+}
+
+#chat .one-chat input.submit {
+       right: 0;
+       width: 35px;
+}
+
+/* END CHAT STYLE */
diff --git a/jappixmini/jappix/css/mucadmin.css b/jappixmini/jappix/css/mucadmin.css
new file mode 100644 (file)
index 0000000..3fe1c75
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+
+Jappix - An open social platform
+This is the mucadmin CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 11/05/11
+
+*/
+
+#mucadmin .content {
+       padding: 10px 0 10px 0;
+}
+
+#mucadmin .content p {
+       margin: 5px 10px 5px 10px;
+       text-align: justify;
+}
+
+#mucadmin .mucadmin-head-jid {
+       text-decoration: underline;
+       font-size: 0.9em;
+       float: right;
+       margin: 1px 4px 1px 1px;
+}
+
+#mucadmin .mucadmin-forms {
+       height: 310px;
+       width: 620px;
+       margin: -5px 0 0 10px;
+       padding: 6px 0 0 0;
+       overflow: auto;
+}
+
+#mucadmin .mucadmin-forms label {
+       width: 260px;
+}
+
+#mucadmin .mucadmin-topic label,
+#mucadmin .mucadmin-aut label,
+#mucadmin .mucadmin-others label {
+       font-size: 0.9em;
+}
+
+#mucadmin .mucadmin-forms textarea {
+       height: 60px;
+       width: 300px;
+       margin: 5px 12px 10px 0;
+}
+
+#mucadmin .results {
+       height: auto;
+       width: auto;
+       overflow: visible;
+       margin: 5px;
+}
+
+#mucadmin .aut-group {
+       float: left;
+       padding-bottom: 4px;
+}
+
+#mucadmin .one-aut {
+       clear: both;
+       margin: 0 10px 5px 0;
+}
+
+#mucadmin .aut-add {
+       clear: both;
+       float: left;
+       margin-bottom: 5px;
+       font-size: 0.9em;
+}
+
+#mucadmin .aut-remove {
+       float: left;
+}
+
+#mucadmin .aut-remove:hover,
+#mucadmin .aut-remove:focus {
+       font-weight: bold;
+       text-decoration: none;
+}
+
+#mucadmin .mucadmin-others a {
+       float: left;
+       font-size: 0.9em;
+}
diff --git a/jappixmini/jappix/css/myinfos.css b/jappixmini/jappix/css/myinfos.css
new file mode 100644 (file)
index 0000000..8326226
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+
+Jappix - An open social platform
+This is the my-infos CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 31/08/11
+
+*/
+
+#my-infos {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.85);
+       color: #919191;
+       margin-top: 8px;
+       padding: 15px 6px 6px 6px;
+       border-radius: 4px;
+       -moz-border-radius: 4px;
+       -webkit-border-radius: 4px;
+       box-shadow: 0 0 6px #5c5c5c;
+       -moz-box-shadow: 0 0 6px #5c5c5c;
+       -webkit-box-shadow: 0 0 6px #5c5c5c;
+}
+
+#my-infos .content {
+       background: #e8f1f3;
+       background: -moz-linear-gradient(top, #e4edef, #e8f1f3);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e4edef), to(#e8f1f3));
+       color: #919191;
+       max-height: 140px;
+       padding: 1px 0;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+#my-infos .element {
+       height: 24px;
+       margin: 6px 0;
+       position: relative;
+}
+
+#my-infos .element .icon {
+       background-color: white;
+       border-color: #636363;
+       border-width: 1px;
+       border-style: solid;
+       margin-left: 6px;
+       height: 22px;
+       width: 25px;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+#my-infos .element div.bubble a {
+       width: 100%;
+       height: 20px;
+}
+
+#my-infos .element .icon:hover,
+#my-infos .element div.bubble a:hover {
+       background-color: #f4f4f4;
+}
+
+#my-infos .element .icon:active,
+#my-infos .element div.bubble a:active {
+       background-color: #ededed;
+}
+
+#my-infos .f-presence div.bubble a[data-value=available] {
+       background-position: 4px -167px;
+}
+
+#my-infos .f-presence div.bubble a[data-value=away] {
+       background-position: 4px -183px;
+}
+
+#my-infos .f-presence div.bubble a[data-value=xa] {
+       background-position: 4px -199px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=crazy] {
+       background-position: 4px -296px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=excited] {
+       background-position: 4px -314px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=playful] {
+       background-position: 4px -332px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=happy] {
+       background-position: 4px -350px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=shocked] {
+       background-position: 4px -368px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=hot] {
+       background-position: 4px -386px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=sad] {
+       background-position: 4px -404px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=amorous] {
+       background-position: 4px -422px;
+}
+
+#my-infos .f-mood div.bubble a[data-value=confident] {
+       background-position: 4px -440px;
+}
+
+#my-infos .f-mood a[data-value] span {
+       background-position: 0 -352px;
+}
+
+#my-infos .f-mood a[data-value=crazy] span,
+.mood-one {
+       background-position: 0 -298px;
+}
+
+#my-infos .f-mood a[data-value=excited] span,
+.mood-two {
+       background-position: 0 -316px;
+}
+
+#my-infos .f-mood a[data-value=playful] span,
+.mood-three {
+       background-position: 0 -334px;
+}
+
+#my-infos .f-mood a[data-value=happy] span,
+.mood-four {
+       background-position: 0 -352px;
+}
+
+#my-infos .f-mood a[data-value=shocked] span,
+.mood-five {
+       background-position: 0 -370px;
+}
+
+#my-infos .f-mood a[data-value=hot] span,
+.mood-six {
+       background-position: 0 -388px;
+}
+
+#my-infos .f-mood a[data-value=sad] span,
+.mood-seven {
+       background-position: 0 -406px;
+}
+
+#my-infos .f-mood a[data-value=amorous] span,
+.mood-eight {
+       background-position: 0 -424px;
+}
+
+#my-infos .f-mood a[data-value=confident] span,
+.mood-nine {
+       background-position: 0 -442px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=doing_chores] {
+       background-position: 4px -458px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=drinking] {
+       background-position: 4px -476px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=eating] {
+       background-position: 4px -494px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=exercising] {
+       background-position: 4px -512px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=grooming] {
+       background-position: 4px -548px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=having_appointment] {
+       background-position: 4px -566px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=inactive] {
+       background-position: 4px -530px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=relaxing] {
+       background-position: 4px -620px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=talking] {
+       background-position: 4px -602px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=traveling] {
+       background-position: 4px -584px;
+}
+
+#my-infos .f-activity div.bubble a[data-value=working] {
+       background-position: 4px -638px;
+}
+
+#my-infos .f-activity a[data-value] span {
+       background-position: 0 -514px;
+}
+
+#my-infos .f-activity a[data-value=doing_chores] span,
+.activity-doing_chores {
+       background-position: 0 -460px;
+}
+
+#my-infos .f-activity a[data-value=drinking] span,
+.activity-drinking {
+       background-position: 0 -478px;
+}
+
+#my-infos .f-activity a[data-value=eating] span,
+.activity-eating {
+       background-position: 0 -496px;
+}
+
+#my-infos .f-activity a[data-value=exercising] span,
+.activity-exercising {
+       background-position: 0 -514px;
+}
+
+#my-infos .f-activity a[data-value=grooming] span,
+.activity-grooming {
+       background-position: 0 -550px;
+}
+
+#my-infos .f-activity a[data-value=having_appointment] span,
+.activity-having_appointment {
+       background-position: 0 -568px;
+}
+
+#my-infos .f-activity a[data-value=inactive] span,
+.activity-inactive {
+       background-position: 0 -532px;
+}
+
+#my-infos .f-activity a[data-value=relaxing] span,
+.activity-relaxing {
+       background-position: 0 -622px;
+}
+
+#my-infos .f-activity a[data-value=talking] span,
+.activity-talking {
+       background-position: 0 -604px;
+}
+
+#my-infos .f-activity a[data-value=traveling] span,
+.activity-traveling {
+       background-position: 0 -586px;
+}
+
+#my-infos .f-activity a[data-value=working] span,
+.activity-working {
+       background-position: 0 -640px;
+}
+
+#my-infos .element .icon.picker {
+       border-width: 1px 0 1px 1px;
+       border-top-right-radius: 0;
+       border-bottom-right-radius: 0;
+       -moz-border-radius-topright: 0;
+       -moz-border-radius-bottomright: 0;
+       -webkit-border-top-right-radius: 0;
+       -webkit-border-bottom-right-radius: 0;
+}
+
+#my-infos .element .icon.disabled {
+       background-color: #f3f3f3;
+       border-color: #989898;
+       cursor: default;
+}
+
+#my-infos .element div.bubble {
+       background-color: white;
+       border-color: #636363;
+       border-width: 1px 1px 0 1px;
+       border-style: solid;
+       width: 25px;
+       padding: 1px 0;
+       position: absolute;
+       bottom: 21px;
+       left: 6px;
+       border-top-left-radius: 2px;
+       border-top-right-radius: 2px;
+       -moz-border-radius-topleft: 2px;
+       -moz-border-radius-topright: 2px;
+       -webkit-border-top-left-radius: 2px;
+       -webkit-border-top-right-radius: 2px;
+}
+
+#my-infos .element a {
+       float: left;
+}
+
+#my-infos .element .icon span {
+       height: 16px;
+       width: 16px;
+       margin: 3px 4px;
+       display: block;
+}
+
+#my-infos .element input {
+       height: 18px;
+       width: 190px;
+       font-size: 0.85em;
+       padding-left: 4px;
+       border-top-left-radius: 0;
+       border-bottom-left-radius: 0;
+       -moz-border-radius-topleft: 0;
+       -moz-border-radius-bottomleft: 0;
+       -webkit-border-top-left-radius: 0;
+       -webkit-border-top-bottom-radius: 0;
+}
diff --git a/jappixmini/jappix/css/options.css b/jappixmini/jappix/css/options.css
new file mode 100644 (file)
index 0000000..6dc4ecd
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+
+Jappix - An open social platform
+This is the options CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/04/11
+
+*/
+
+#options label {
+       width: 190px;
+       font-size: 0.94em;
+}
+
+#options .forms {
+       width: 610px;
+       height: 328px;
+       margin: 15px 15px 15px 15px;
+       float: left;
+}
+
+#options .forms select {
+       margin-top: -3px;
+       min-width: 120px;
+       float: left;
+}
+
+#options .forms a.linked {
+       font-size: 0.9em;
+       float: left;
+}
+
+#options fieldset.privacy {
+       display: none;
+}
+
+#options .sub-ask-delete, #options .sub-ask-pass, #options .sub-ask-pass-success {
+       display: none;
+}
+
+#options .sub-ask {
+       display: none;
+       width: 592px;
+       padding: 8px;
+       float: left;
+       border: 1px #879da2 dotted;
+       background: #cbdde1;
+}
+
+#options .sub-ask-top {
+       font-size: 0.9em;
+       margin-top: -3px;
+}
+
+#options .sub-ask-title {
+       margin-bottom: 4px;
+       float: left;
+}
+
+#options .sub-ask-close {
+       float: right;
+}
+
+#options .sub-ask-close:hover {
+       cursor: pointer;
+}
+
+#options .sub-ask-content {
+       clear: both;
+       height: 25px;
+       font-size: 0.9em;
+       border-top: 1px #416972 solid;
+       padding: 12px 0;
+}
+
+#options .sub-ask-content label {
+       width: 125px;
+}
+
+#options .sub-ask-content input {
+       width: 125px;
+}
+
+#options .sub-ask-bottom {
+       clear: both;
+       font-size: 0.9em;
+       float: right;
+       text-decoration: underline;
+}
+
+#options .sub-ask-bottom:hover {
+       cursor: pointer;
+}
diff --git a/jappixmini/jappix/css/others.css b/jappixmini/jappix/css/others.css
new file mode 100644 (file)
index 0000000..f3e2461
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+Jappix - An open social platform
+This is the others CSS stylesheet for Jappix
+-------------------------------------------------
+License: AGPL
+Author: Vanaryon
+Last revision: 31/08/11
+*/
+#audio {
+        display: none;
+}
+#top-content {
+        position: absolute;
+        right: 5px;
+        left: 5px;
+        top: 0;
+        min-width: 860px;
+        z-index: 50;
+}
+#main-content {
+        position: absolute;
+        top: 34px;
+        left: 5px;
+        right: 5px;
+        bottom: 5px;
+        min-width: 850px;
+        min-height: 450px;
+}
+#left-content {
+        position: absolute;
+        top: 0;
+        left: 0;
+        bottom: 0;
+        width: 248px;
+}
+#right-content {
+        background-color: rgb(20,20,20);
+        background-color: rgba(20,20,20,0.85);
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 260px;
+        z-index: 10;
+        border-radius: 4px;
+        -moz-border-radius: 4px;
+        -webkit-border-radius: 4px;
+        box-shadow: 0 0 6px #5c5c5c;
+        -moz-box-shadow: 0 0 6px #5c5c5c;
+        -webkit-box-shadow: 0 0 6px #5c5c5c;
+}
+#general-wait {
+       background: url(../img/others/blank.gif) repeat;
+        z-index: 10000;
+        position: fixed;
+        top: 0;
+        bottom: 0;
+        left: 0;
+        right: 0;
+}
+.general-wait-content {
+        background-color: rgb(255,255,255);
+        background-color: rgba(255,255,255,0.9);
+        background-position: 8px 8px;
+        padding: 8px;
+        position: absolute;
+        right: 5px;
+        bottom: 5px;
+        border-radius: 4px;
+        -moz-border-radius: 4px;
+        -webkit-border-radius: 4px;
+        box-shadow: 0 0 2px #000;
+        -moz-box-shadow: 0 0 2px #000;
+        -webkit-box-shadow: 0 0 2px #000;
+}
+.inbox-hidable,
+.options-hidable,
+.pep-hidable,
+.pubsub-hidable,
+.archives-hidable,
+.commands-hidable,
+.privacy-hidable,
+.xmpplinks-hidable {
+        display: none;
+}
+#reconnect .pane {
+        background-color: rgb(20,20,20);
+        background-color: rgba(20,20,20,0.85);
+        color: white;
+        padding: 25px;
+        z-index: 10000;
+        text-shadow: 0 1px 1px black;
+        position: absolute;
+        left: 0;
+        right: 0;
+        top: 0;
+        box-shadow: 0 0 35px #232323;
+        -moz-box-shadow: 0 0 35px #232323;
+        -webkit-box-shadow: 0 0 35px #232323;
+}
+#reconnect .pane a {
+        margin-top: -4px;
+        float: right;
+}
diff --git a/jappixmini/jappix/css/pageengine.css b/jappixmini/jappix/css/pageengine.css
new file mode 100644 (file)
index 0000000..75038b6
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+
+Jappix - An open social platform
+This is the page-engine CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 31/08/11
+
+*/
+
+#page-engine {
+       background-color: #f4f4f4;
+       position: absolute;
+       top: 40px;
+       bottom: 6px;
+       right: 6px;
+       left: 6px;
+       z-index: 8;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+#page-engine .top {
+       background: #e8f1f3;
+       background: -moz-linear-gradient(top, #e8f1f3, #dee8ea);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e8f1f3), to(#dee8ea));
+       border-bottom: 1px solid #d0d0d0;
+       color: black;
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       padding: 6px;
+       height: 80px;
+       border-top-right-radius: 3px;
+       border-top-left-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -moz-border-radius-topleft: 3px;
+       -webkit-border-top-right-radius: 3px;
+       -webkit-border-top-left-radius: 3px;
+}
+
+#page-engine .top .avatar-container {
+       text-align: center;
+       margin: 2px 0 0 10px;
+       height: 76px;
+       width: 76px;
+       float: left;
+}
+
+#page-engine .top .avatar {
+       max-height: 76px;
+       max-width: 76px;
+}
+
+#page-engine .top .name {
+       text-align: right;
+       padding: 7px;
+}
+
+#page-engine p.bc-name {
+       font-size: 2.3em;
+       margin-bottom: 5px;
+}
+
+#page-engine p.bc-infos {
+       font-size: 0.85em;
+       height: 16px;
+       overflow: hidden;
+       position: absolute;
+       left: 115px;
+       right: 12px;
+}
+
+#page-engine .page-engine-chan[data-type=groupchat] p.bc-infos {
+       left: 12px;
+}
+
+#page-engine p.bc-infos span.show {
+       padding-left: 18px;
+}
+
+#page-engine p.bc-infos a {
+       text-decoration: underline;
+}
+
+#page-engine div.bc-pep {
+       float: right;
+}
+
+#page-engine div.bc-pep a {
+       height: 16px;
+       width: 16px;
+       margin-left: 4px;
+       float: left;
+}
+
+#page-engine div.bc-pep a:hover {
+       cursor: default;
+}
+
+#page-engine div.bc-pep a[href]:hover {
+       cursor: pointer;
+}
+
+#page-engine .content,
+#page-engine .list {
+       font-size: 0.9em;
+       position: absolute;
+       top: 93px;
+       right: 0;
+       bottom: 29px;
+       overflow: auto;
+       box-shadow: inset 0 3px 10px #e8e8e8;
+       -moz-box-shadow: inset 0 3px 10px #e8e8e8;
+       -webkit-box-shadow: inset 0 3px 10px #e8e8e8;
+}
+
+#page-engine .content {
+       left: 0;
+       padding: 12px 14px 0;
+}
+
+#page-engine .content a {
+       text-decoration: underline;
+}
+
+#page-engine .page-engine-chan {
+       display: none;
+}
+
+#page-engine .chat .content,
+#page-engine .chat .list {
+       bottom: 93px;
+}
+
+#page-engine .chat .content {
+       padding-bottom: 24px;
+}
+
+#page-engine .groupchat-content {
+       padding-bottom: 16px !important;
+       right: 191px !important;
+}
+
+#page-engine .list {
+       border-left: 1px solid #c8c8c8;
+       padding: 8px 0 0;
+       width: 190px;
+       right: 0;
+}
+
+#page-engine .list .role {
+       display: none;
+       margin-bottom: 10px;
+}
+
+#page-engine .list .title {
+       font-weight: bold;
+       color: #383838;
+       margin-left: 8px;
+}
+
+#page-engine .list .user {
+       background: #eff2f2;
+       background: -moz-linear-gradient(top, #eff2f2, #ecefef);
+       background: -webkit-gradient(linear, left top, left bottom, from(#eff2f2), to(#ecefef));
+       border-color: #c8c8c8;
+       border-width: 1px 0;
+       border-style: solid;
+       color: #383838;
+       margin-bottom: 3px;
+       height: 32px;
+       overflow: hidden;
+}
+
+#page-engine .list .user:hover {
+       background: #e9ecec;
+       cursor: pointer;
+}
+
+#page-engine .list .user:active {
+       background: #e3e7e7;
+}
+
+#page-engine .list .user.myself {
+       background-color: #eff2f2;
+       cursor: default;
+}
+
+#page-engine .list .user .name {
+       float: left;
+       height: 18px;
+       overflow: hidden;
+       margin: 7px 0 7px 3px;
+       padding-left: 18px;
+}
+
+#page-engine .list .user .avatar-container {
+       text-align: center;
+       float: right;
+       height: 32px;
+       width: 32px;
+}
+
+#page-engine .list .user .avatar {
+       max-height: 32px;
+       max-width: 32px;
+}
+
+#page-engine .one-group,
+#archives .one-group {
+       border-bottom: 1px dotted #d0d0d0;
+       padding-bottom: 8px;
+       margin-bottom: 10px;
+}
+
+#page-engine .one-line,
+#archives .one-line,
+#page-engine .one-group b.name,
+#archives .one-group b.name {
+       padding-left: 50px;
+       word-wrap: break-word;
+}
+
+#page-engine .one-group b.name,
+#archives .one-group b.name {
+       display: block;
+       margin-bottom: 4px;
+}
+
+#page-engine .one-group b.name.me,
+#archives .one-group b.name.me {
+       color: #123a5c;
+}
+
+#page-engine .one-group b.name.him,
+#archives .one-group b.name.him {
+       color: #801e1e;
+}
+
+#page-engine .one-group span.date,
+#archives .one-group span.date {
+       float: right;
+       font-size: 0.9em;
+}
+
+#page-engine .one-group .avatar-container,
+#archives .one-group .avatar-container {
+       text-align: center;
+       margin: 4px 0 0 6px;
+       height: 30px;
+       width: 30px;
+       float: left;
+}
+
+#page-engine .one-group .avatar,
+#archives .one-group .avatar {
+       max-height: 30px;
+       max-width: 30px;
+}
+
+#page-engine b.name.talk-images {
+       background-position: 50px -99px;
+       padding-left: 68px;
+}
+
+#page-engine .user-message,
+#archives .user-message {
+       margin-bottom: 3px;
+}
+
+#page-engine .system-message {
+       color: #053805 !important;
+       margin-bottom: 3px !important;
+       padding-left: 0 !important;
+}
+
+#page-engine .system-message a {
+       color: #053805 !important;
+}
+
+#page-engine .system-message p.help b {
+       margin-bottom: 5px;
+       text-decoration: underline;
+       display: block;
+}
+
+#page-engine .system-message p.help em {
+       width: 240px;
+       text-decoration: underline;
+       margin-left: 5px;
+       float: left;
+}
+
+#page-engine .my-nick {
+       font-weight: bold;
+}
+
+#page-engine .old-message {
+       font-size: 11px !important;
+       margin-bottom: 1px !important;
+}
+
+#page-engine .chatstate {
+       background-color: rgb(234,234,234);
+       background-color: rgba(234,234,234,0.8);
+       color: #2c2c2c;
+       padding: 3px 10px 2px 8px;
+       position: absolute;
+       bottom: 93px;
+       left: 0;
+       font-size: 0.75em;
+       border-top-right-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -webkit-border-top-right-radius: 3px;
+}
+
+#page-engine .text {
+       height: 93px;
+       position: absolute;
+       bottom: 0;
+       left: 0;
+       right: 0;
+}
+
+#page-engine .footer {
+       background: #e8f1f3;
+       background: -moz-linear-gradient(top, #dee8ea, #e8f1f3);
+       background: -webkit-gradient(linear, left top, left bottom, from(#dee8ea), to(#e8f1f3));
+       border-color: #d0d0d0;
+       border-width: 1px 0 0;
+       border-style: solid;
+       color: black;
+       position: absolute;
+       left: 0;
+       right: 0;
+       padding: 6px;
+       height: 16px;
+}
+
+#page-engine .chat .footer {
+       border-width: 1px 0;
+       position: static;
+}
+
+#page-engine .chat-tools-content {
+       height: 16px;
+       width: 16px;
+       margin-right: 8px;
+       float: left;
+}
+
+#page-engine .tools-tooltip {
+       display: block;
+       height: 16px;
+       width: 16px;
+       overflow: hidden;
+       float: left;
+}
+
+#page-engine .text .chat-tools-smileys {
+       margin-left: 4px;
+}
+
+#page-engine .text .chat-tools-file {
+       display: none;
+}
+
+#page-engine .text .chat-tools-file.mini .bubble-file {
+       z-index: 39;
+}
+
+#page-engine .text .chat-tools-file.mini .tooltip-subitem {
+       width: 22px;
+       height: 20px;
+}
+
+#page-engine .text .chat-tools-file.mini .wait {
+       margin: -2px 0 0 -1px;
+}
+
+#page-engine .text .tools-smileys {
+       background-position: 0 -388px;
+}
+
+#page-engine .text .tools-style {
+       background-position: 0 -700px;
+}
+
+#page-engine .text .tools-file {
+       background-position: 0 -1956px;
+}
+
+#page-engine .text .tools-save {
+       background-position: 0 -719px;
+}
+
+#page-engine .text .tools-clear {
+       background-position: 0 -739px;
+}
+
+#page-engine .text .tools-infos,
+#channel .top div.shortcuts a.profile {
+       background-position: 0 -758px;
+}
+
+#page-engine .text .tools-add,
+#page-engine .text .tools-archives,
+#page-engine .text .tools-mucadmin {
+       display: none;
+}
+
+#page-engine .text .tools-mucadmin {
+       background-position: 0 -777px;
+}
+
+#page-engine .bubble-style label.bold {
+       font-weight: bold;
+}
+
+#page-engine .bubble-style label.italic {
+       font-style: italic;
+}
+
+#page-engine .bubble-style label.underline {
+       text-decoration: underline;
+}
+
+#page-engine .bubble-style a.color {
+       height: 18px;
+       width: 18px;
+       border-color: white;
+       border-width: 1px;
+       border-style: solid;
+       margin: 6px 5px 0 0;
+       float: left;
+       opacity: 0.6;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 5px black;
+       -moz-box-shadow: 0 0 5px black;
+       -webkit-box-shadow: 0 0 5px black;
+}
+
+#page-engine .bubble-style a.color:hover,
+#page-engine .bubble-style a.color:focus {
+       opacity: 0.7;
+}
+
+#page-engine .bubble-style a.color.selected {
+       opacity: 1;
+       border-color: #ffb20d;
+}
+
+#page-engine .bubble-file .tooltip-subitem {
+       width: 240px;
+}
+
+#page-engine .bubble-file input[type=file] {
+       width: 220px;
+}
+
+#page-engine .bubble-file input[type=submit],
+#page-engine .bubble-file input[type=reset] {
+       margin: 4px 4px 0 0;
+}
+
+#page-engine .text .compose,
+#page-engine .muc-ask {
+       position: absolute;
+       left: 0;
+}
+
+#page-engine .text .compose {
+       top: 29px;
+       right: 12px;
+       bottom: 12px;
+}
+
+#page-engine .muc-ask {
+       right: 0;
+       bottom: 0;
+}
+
+#page-engine .text textarea {
+       border: 1px solid #c8c8c8;
+       padding: 5px;
+       height: 100%;
+       width: 100%;
+       font-size: 1.1em;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       border-top-right-radius: 0;
+       border-top-left-radius: 0;
+       -moz-border-radius-topright: 0;
+       -moz-border-radius-topleft: 0;
+       -webkit-border-top-right-radius: 0;
+       -webkit-border-top-left-radius: 0;
+}
+
+#page-engine .muc-ask {
+       background-color: #e8f1f3;
+       height: 64px;
+       font-size: 0.9em;
+       right: 0;
+       z-index: 2;
+       border-bottom-left-radius: 3px;
+       border-bottom-right-radius: 3px;
+       -moz-border-radius-bottomleft: 3px;
+       -moz-border-radius-bottomright: 3px;
+       -webkit-border-bottom-left-radius: 3px;
+       -webkit-border-bottom-right-radius: 3px;
+}
+
+#page-engine .muc-ask label {
+       color: #224249;
+       margin: 23px 10px 0 16px;
+       font-weight: bold;
+}
+
+#page-engine .muc-ask input {
+       width: 200px;
+       margin: 19px 10px 0 10px;
+       padding: 3px;
+}
+
+#page-engine .tooltip {
+       position: absolute;
+       bottom: 84px;
+       margin-left: -13px;
+       z-index: 40;
+       font-size: 0.8em;
+       color: white;
+}
+
+#page-engine .tooltip a {
+       color: white;
+       text-decoration: underline;
+}
+
+#page-engine .tooltip-subitem {
+       background-color: rgb(0,0,0);
+       background-color: rgba(0,0,0,0.8);
+       padding: 10px;
+       width: 200px;
+       height: 110px;
+       text-shadow: 0 1px 1px black;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+
+#page-engine .tooltip-subarrow {
+       background-position: 0 -251px;
+       opacity: 0.8;
+       height: 10px;
+       width: 18px;
+       margin-left: 12px;
+}
+
+#page-engine .tooltip .tooltip-top {
+       margin-bottom: 8px;
+       font-weight: bold;
+}
+
+#page-engine .tooltip label {
+       margin-bottom: 4px;
+       float: left;
+       clear: both;
+}
+
+#page-engine .tooltip label input[type=checkbox] {
+       margin: 0 6px 0 0;
+       float: left;
+}
+
+#page-engine .tooltip label.select {
+       margin-top: 5px;
+}
+
+#page-engine .tooltip input,
+#page-engine .tooltip select {
+       float: left;
+}
+
+#page-engine .tooltip select {
+       width: 100px;
+}
+
+#page-engine .tooltip .tooltip-actionlog:hover,
+#page-engine .tooltip .tooltip-actionlog:focus {
+       cursor: pointer;
+       text-decoration: underline;
+}
diff --git a/jappixmini/jappix/css/pageswitch.css b/jappixmini/jappix/css/pageswitch.css
new file mode 100644 (file)
index 0000000..5983004
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+
+Jappix - An open social platform
+This is the page-switch CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 22/05/11
+
+*/
+
+#page-switch {
+       position: absolute;
+       top: 15px;
+       left: 10px;
+       right: 10px;
+       z-index: 9;
+}
+
+#page-switch .chans {
+       position: absolute;
+       left: 0;
+       right: 40px;
+       top: 0;
+       height: 25px;
+       overflow: hidden;
+}
+
+#page-switch .more {
+       position: absolute;
+       right: 0;
+       top: 0;
+}
+
+#page-switch .more-button {
+       background-position: 6px -1372px;
+       background-color: #d9e7ea;
+       width: 7px;
+       height: 17px;
+       padding: 1px 6px;
+       font-size: 0.9em;
+       text-decoration: none;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+#page-switch .more-content {
+       background-color: #d9e7ea;
+       width: 200px;
+       max-height: 400px;
+       overflow: auto;
+       position: absolute;
+       margin: -2px 0 0 -181px;
+       padding: 4px 0;
+       font-size: 0.95em;
+       border-top-left-radius: 3px;
+       border-bottom-left-radius: 3px;
+       border-bottom-right-radius: 3px;
+       -moz-border-radius-topleft: 3px;
+       -moz-border-radius-bottomleft: 3px;
+       -moz-border-radius-bottomright: 3px;
+       -webkit-border-top-left-radius: 3px;
+       -webkit-border-bottom-left-radius: 3px;
+       -webkit-border-bottom-right-radius: 3px;
+}
+
+#page-switch .switcher {
+       background-color: #d9e7ea;
+       color: #17353b;
+       height: 15px;
+       padding: 5px 10px 5px 5px;
+       margin: 0 2px;
+       font-size: 0.85em;
+       float: left;
+       border-top-right-radius: 3px;
+       border-top-left-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -moz-border-radius-topleft: 3px;
+       -webkit-border-top-right-radius: 3px;
+       -webkit-border-top-left-radius: 3px;
+}
+
+#page-switch .more-content .switcher {
+       background-color: #d9e7ea;
+       float: none;
+       margin: 0;
+       font-size: 0.9em;
+       border-radius: 0;
+       -moz-border-radius: 0;
+       -webkit-border-radius: 0;
+}
+
+#page-switch .more-content .switcher .exit {
+       display: block;
+}
+
+#page-switch .more-button:hover,
+#page-switch .more-button:focus,
+#page-switch .switcher:hover,
+#page-switch .switcher:focus,
+#page-switch .more-content .switcher:hover,
+#page-switch .more-content .switcher:focus {
+       background-color: #cedee1;
+       cursor: pointer;
+}
+
+#page-switch .more-button:active,
+#page-switch .switcher:active,
+#page-switch .more-content .switcher:active {
+       background-color: #c3d3d7;
+}
+
+#page-switch .switcher.activechan {
+       background-color: #e8f1f3;
+}
+
+#page-switch .more-content .switcher.activechan {
+       background-color: #d1e0e3;
+}
+
+#page-switch .icon {
+       height: 16px;
+       width: 16px;
+       float: left;
+}
+
+#page-switch .name {
+       float: left;
+       margin-left: 4px;
+       max-height: 16px;
+       max-width: 140px;
+       overflow: hidden;
+}
+
+#page-switch .exit {
+       display: none;
+       background-color: #bdd9dc;
+       border: 1px solid #80aab0;
+       color: #355e64;
+       height: 14px;
+       width: 13px;
+       margin-left: 10px;
+       font-size: 0.85em;
+       text-align: center;
+       text-decoration: none;
+       float: right;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+#page-switch .exit:hover,
+#page-switch .exit:focus {
+       background-color: #aac7cb;
+}
+
+#page-switch .exit:active {
+       background-color: #9bbdc1;
+}
+
+#page-switch .activechan .exit {
+       display: block;
+       float: right;
+}
+
+#page-switch .chan-newmessage {
+       background-color: #f6edc3 !important;
+}
+
+#page-switch .chan-newmessage:hover,
+#page-switch .chan-newmessage:focus {
+       background-color: #f1eac0 !important;
+}
+
+#page-switch .chan-newmessage:active {
+       background-color: #ede4b8 !important;
+}
+
+#page-switch .composing,
+#page-engine .list .user.composing {
+       color: #217021 !important;
+}
+
+#page-switch .paused,
+#page-switch .chan-unread .name,
+#page-engine .list .user.paused {
+       color: #2431ac !important;
+}
+
+#page-switch .active,
+#page-engine .list .user.active {
+       color: #353535 !important;
+}
+
+#page-switch .inactive,
+#page-engine .list .user.inactive {
+       color: #585858 !important;
+}
+
+#page-switch .gone {
+       color: #851313 !important;
+}
+
+#page-switch .channel .icon {
+       background-position: 0 -55px;
+}
diff --git a/jappixmini/jappix/css/popup.css b/jappixmini/jappix/css/popup.css
new file mode 100644 (file)
index 0000000..e5b3eb9
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+
+Jappix - An open social platform
+This is the popup CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 02/05/11
+
+*/
+
+.lock {
+       background-color: rgb(0,0,0);
+       background-color: rgba(0,0,0,0.6);
+       left: 0;
+       right: 0;
+       top: 0;
+       bottom: 0;
+       position: fixed;
+       z-index: 9999;
+}
+
+.popup {
+       background-color: rgb(20,20,20);
+       background-color: rgba(20,20,20,0.95);
+       margin-top: -250px;
+       margin-left: -330px;
+       width: 640px;
+       height: 500px;
+       padding: 0 10px;
+       position: absolute;
+       z-index: 10000;
+       left: 50%;
+       top: 50%;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+       box-shadow: 0 0 35px #232323;
+       -moz-box-shadow: 0 0 35px #232323;
+       -webkit-box-shadow: 0 0 35px #232323;
+}
+
+.popup.large {
+       margin-left: -460px;
+       width: 920px;
+}
+
+.popup .top {
+       width: 600px;
+       height: 45px;
+       font-size: 1.2em;
+       padding-top: 9px;
+       color: white;
+       margin: 14px 0 0 40px;
+       text-transform: uppercase;
+       text-decoration: none;
+       font-weight: bold;
+       text-shadow: 0 2px 2px black;
+}
+
+.popup .tab {
+       width: 620px;
+       height: 25px;
+       margin: -5px 10px 0 10px;
+       position: relative;
+       z-index: 1;
+}
+
+.popup .tab a {
+       background-color: #d9e7ea;
+       color: #204249;
+       width: 180px;
+       height: 17px;
+       padding: 4px 4px 4px 16px;
+       margin-left: 5px;
+       font-size: 0.94em;
+       overflow: hidden;
+       float: left;
+       border-top-right-radius: 3px;
+       border-top-left-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -moz-border-radius-topleft: 3px;
+       -webkit-border-top-right-radius: 3px;
+       -webkit-border-top-left-radius: 3px;
+}
+
+.popup .tab a:hover,
+.popup .tab a:focus {
+       background-color: #cedee1;
+       text-decoration: none;
+}
+
+.popup .tab a:active {
+       background-color: #c3d3d7;
+       text-decoration: none;
+}
+
+.popup .tab a.tab-active {
+       background-color: #e4eef9 !important;
+}
+
+.popup .one-lap {
+       display: none;
+}
+
+.popup .one-lap.lap-active {
+       display: block;
+}
+
+.popup .content {
+       background: #e4eef9;
+       background: -moz-linear-gradient(top, #e4eef9, #D0E5FA);
+       background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#D0E5FA));
+       height: 358px;
+       width: 640px;
+       position: absolute;
+       left: 10px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 20px black;
+       -moz-box-shadow: 0 0 20px black;
+       -webkit-box-shadow: 0 0 20px black;
+}
+
+.popup .content,
+.popup .content a {
+       color: #112a2f;
+}
+
+.popup.large div.comments {
+       background-color: #f4f4f4;
+       width: 272px;
+       margin: 0;
+       position: absolute;
+       right: 10px;
+       top: 63px;
+       bottom: 10px;
+       overflow-x: hidden;
+       overflow-y: auto;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+.popup.large div.comments div.comments-content {
+       font-size: 0.8em;
+}
+
+.popup.large div.comments input {
+       width: 185px;
+       min-width: 0;
+}
+
+.popup.large div.comments .one-comment {
+       padding-bottom: 4px;
+}
+
+.popup.large div.comments .one-comment a {
+       text-decoration: underline;
+}
+
+.popup.large div.comments div.comments-content {
+       border-top-right-radius: 3px;
+       border-top-left-radius: 3px;
+       -moz-border-radius-topright: 3px;
+       -moz-border-radius-topleft: 3px;
+       -webkit-border-top-right-radius: 3px;
+       -webkit-border-top-left-radius: 3px;
+}
+
+.popup .head {
+       background: #f1f6fd;
+       border: 1px #9dc4fc solid;
+       width: 606px;
+       height: 24px;
+       margin: 0 10px 10px 10px;
+       padding: 6px;
+}
+
+.popup .head-text {
+       float: left;
+       font-size: 0.9em;
+       margin: 3px;
+}
+
+.popup .head-actions {
+       float: right;
+       margin-top: 2px;
+}
+
+.popup .head-actions a {
+       font-size: 0.9em;
+       margin: 0 4px;
+}
+
+.popup .actions a {
+       color: #30575f;
+       font-size: 0.9em;
+       margin-left: 5px;
+}
+
+.popup .head .head-input {
+       float: right;
+       width: 200px;
+       padding: 2px;
+}
+
+.popup .head .head-select {
+       float: right;
+       height: 24px;
+}
+
+.popup .forms {
+       width: 390px;
+       height: 328px;
+       margin: 15px;
+       float: left;
+}
+
+.popup fieldset {
+       border: 1px #547177 solid;
+       margin: 0 0 15px 0;
+       padding: 8px 2px 3px 2px;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+}
+
+.popup legend {
+       font-size: 0.9em;
+       margin: 0 0 0 15px;
+       padding: 0 2px;
+       text-transform: uppercase;
+}
+
+.popup label {
+       color: #1b1b1b;
+       width: 150px;
+       margin: 0 0 10px 12px;
+       clear: both;
+       float: left;
+}
+
+.popup input,
+.popup select {
+       margin: 0 10px 10px 0;
+       float: left;
+}
+
+.popup input[type=text] {
+       min-width: 174px;
+}
+
+.popup select {
+       min-height: 20px;
+}
+
+.popup .results {
+       height: 310px;
+       width: 620px;
+       margin: -5px 0 0 10px;
+       padding: 6px 0 0 0;
+       overflow: auto;
+}
+
+.popup .results .no-results {
+       margin: 6px 0;
+       font-size: 0.85em;
+       font-weight: bold;
+}
+
+.popup .results label {
+       width: 180px;
+       margin: 6px 4px 4px 4px;
+}
+
+.popup .results input,
+.popup .results textarea,
+.popup .results select {
+       margin: 4px;
+}
+
+.popup .results input,
+.popup .results select {
+       min-width: 180px;
+}
+
+.popup .results input[type=checkbox],
+.popup .results input[type=radio] {
+       margin-top: 7px;
+}
+
+.popup .results textarea {
+       width: 380px;
+}
+
+.popup .results .avatar-container {
+       float: left;
+       width: 60px;
+       height: 60px;
+       margin: 5px 12px 5px 9px;
+       text-align: center;
+       background-repeat: no-repeat;
+}
+
+.popup .results img.avatar {
+       max-width: 60px;
+       max-height: 60px;
+}
+
+.popup .results .one-icon {
+       height: 16px;
+       width: 16px;
+       margin: 10px 3px 0 8px;
+       float: left;
+}
+
+.popup .results .one-icon.account,
+.popup .results .one-icon.auth {
+       background-position: 0 -777px;
+}
+
+.popup .results .one-icon.automation,
+.popup .results .one-icon.client {
+       background-position: 0 -1500px;
+}
+
+.popup .results .one-icon.collaboration {
+       background-position: 0 -1520px;
+}
+
+.popup .results .one-icon.proxy,
+.popup .results .one-icon.server,
+.popup .results .one-icon.others {
+       background-position: 0 -1540px;
+}
+
+.popup .results .one-icon.component,
+.popup .results .one-icon.gateway {
+       background-position: 0 -1560px;
+}
+
+.popup .results .one-icon.conference {
+       background-position: 0 -1082px;
+}
+
+.popup .results .one-icon.directory {
+       background-position: 0 -876px;
+}
+
+.popup .results .one-icon.headline,
+.popup .results .one-icon.hierarchy {
+       background-position: 0 -1580px;
+}
+
+.popup .results .one-icon.pubsub,
+.popup .results .one-icon.store {
+       background-position: 0 -1600px;
+}
+
+.popup .results .one-icon.loading {
+       background-position: 0 -1620px;
+}
+
+.popup .results .one-icon.down {
+       background-position: 0 -1640px;
+}
+
+.popup .results .one-host {
+       font-weight: bold;
+       width: 170px;
+}
+
+.popup .results .one-type {
+       width: 210px;
+}
+
+.popup .results .one-type,
+.popup .results .one-host {
+       float: left;
+       overflow: hidden;
+       margin: 9px 8px;
+}
+
+.popup .results .one-jid,
+.popup .results .one-ctry,
+.popup .results .one-fn {
+       margin: 4px;
+       width: 400px;
+}
+
+.popup .results .one-fn {
+       font-weight: bold;
+}
+
+.popup .results .one-jid {
+       margin-top: 8px;
+       font-size: 0.9em;
+}
+
+.popup .results .one-name {
+       float: left;
+       margin: 4px;
+}
+
+.popup a.one-button {
+       display: none;
+       background-color: #f1f6fd;
+       border: 1px solid #b9cbcf;
+       margin-top: 1px;
+       padding: 4px 8px;
+       text-decoration: none;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+.popup a.one-button:hover,
+.popup a.one-button:focus {
+       border: 1px solid #95b1b7;
+}
+
+.popup a.one-button:active {
+       border: 1px solid #77989f;
+}
+
+.popup .results .oneresult:hover a.one-button {
+       display: block;
+}
+
+.popup .results a.one-button,
+#inbox .one-message a.one-button {
+       float: right;
+       padding: 3px 6px;
+       margin-right: 4px;
+}
+
+.popup .results a.one-vjud {
+       position: absolute;
+       right: 4px;
+}
+
+.popup .results a.one-add {
+       top: 8px;
+}
+
+.popup .results a.one-chat {
+       top: 42px;
+}
+
+.popup .results .one-next {
+       float: right;
+       margin: 4px 8px 4px 4px;
+       font-weight: bold;
+}
+
+.popup .results .one-actions {
+       width: 148px;
+       margin: 4px;
+       float: left;
+}
+
+.popup .results .one-actions a {
+       width: 16px;
+       height: 16px;
+       padding: 2px 2px 4px 5px !important;
+       margin-top: 2px;
+}
+
+.popup .results .one-actions a.browse {
+       background-position: 3px -1396px;
+}
+
+.popup .results .one-actions a.command {
+       background-position: 3px -1415px;
+}
+
+.popup .results .one-actions a.subscribe {
+       background-position: 4px -1435px;
+}
+
+.popup .results .one-actions a.join {
+       background-position: 3px -1455px;
+}
+
+.popup .results .one-actions a.search {
+       background-position: 4px -1475px;
+}
+
+.popup .results a.submit,
+.popup .results a.cancel,
+.popup .results a.back {
+       margin-right: 8px;
+       float: right;
+}
+
+.popup .onetitle {
+       font-size: 0.9em;
+       padding: 4px;
+       font-weight: bold;
+}
+
+.popup .oneinstructions {
+       font-size: 0.9em;
+       padding: 4px;
+       margin: 8px 0;
+}
+
+.popup .oneresult {
+       font-size: 0.9em;
+       padding: 3px 0 4px 4px;
+       border-bottom: 1px #9dc4fc solid;
+       overflow: hidden;
+       position: relative;
+}
+
+.popup .oneresult:hover {
+       background: #e9f1fd;
+}
+
+.popup .oneresult[onclick]:hover {
+       cursor: pointer;
+}
+
+.popup .oneresult[onclick]:active {
+       background: #f1f6fd;
+}
+
+.popup .infos {
+       background-color: rgb(255,239,104);
+       background-color: rgba(255,239,104,0.8);
+       border: 1px #decb2f solid;
+       color: #3f3f3f;
+       padding: 8px;
+       margin: 10px;
+       font-size: 0.8em;
+}
+
+.popup .infos p {
+       margin-top: 10px;
+}
+
+.popup .infos p.infos-title {
+       font-weight: bold;
+}
+
+.popup .bottom {
+       width: 640px;
+       height: 40px;
+       position: absolute;
+       bottom: 8px;
+}
+
+.popup .wait {
+       display: none;
+       margin: 8px 0 0 3px;
+       float: left;
+}
+
+a.finish {
+       border: 1px solid white;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+       color: white;
+       padding: 4px 8px;
+       margin-right: 7px;
+       font-size: 0.95em;
+       text-align: center;
+       text-decoration: none;
+       text-shadow: 0 1px 1px black;
+       border-radius: 3px;
+       -moz-border-radius: 3px;
+       -webkit-border-radius: 3px;
+       box-shadow: 0 0 5px black;
+       -moz-box-shadow: 0 0 5px black;
+       -webkit-box-shadow: 0 0 5px black;
+}
+
+a.finish:hover,
+a.finish:focus {
+       cursor: pointer;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.2);
+       box-shadow: 0 0 15px black;
+       -moz-box-shadow: 0 0 15px black;
+       -webkit-box-shadow: 0 0 15px black;
+}
+
+a.finish:active {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.3);
+}
+
+a.finish.disabled {
+       opacity: 0.2;
+}
+
+a.finish.disabled:hover,
+a.finish.disabled:focus,
+a.finish.disabled:active {
+       cursor: default;
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+}
+
+.popup a.finish {
+       margin-top: 6px;
+       float: right;
+}
diff --git a/jappixmini/jappix/css/privacy.css b/jappixmini/jappix/css/privacy.css
new file mode 100644 (file)
index 0000000..521be32
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+
+Jappix - An open social platform
+This is the privacy CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/02/11
+
+*/
+
+#privacy .content {
+       padding: 10px 0 10px 0;
+}
+
+#privacy .privacy-head div.list-left,
+#privacy .privacy-head div.list-center,
+#privacy .privacy-head div.list-right,
+#privacy .privacy-first {
+       float: left;
+}
+
+#privacy .privacy-head div.list-left {
+       margin-left: 5px;
+}
+
+#privacy .privacy-head div.list-center {
+       border-right: 1px dotted #1b393f;
+       height: 24px;
+       width: 1px;
+       margin-right: 15px;
+       padding-left: 18px;
+}
+
+#privacy .privacy-head span,
+#privacy .privacy-head a,
+#privacy .privacy-item span,
+#privacy .privacy-item a {
+       float: left;
+}
+
+#privacy .privacy-head span {
+       font-size: 0.9em;
+       font-weight: bold;
+       margin: 3px 10px 0 0;
+}
+
+#privacy .privacy-head input,
+#privacy .privacy-head select {
+       width: 180px;
+}
+
+#privacy .privacy-head input {
+       margin-top: 1px;
+}
+
+#privacy .privacy-head select,
+#privacy .privacy-item select {
+       margin-top: -2px;
+}
+
+#privacy .privacy-head span.left-space {
+       margin-left: 16px;
+}
+
+#privacy .privacy-head a,
+#privacy .privacy-item a {
+       width: 20px;
+       height: 20px;
+       padding: 0;
+       display: block;
+}
+
+#privacy .privacy-item a.item-add {
+       background-position: 2px -1178px;
+}
+
+#privacy .privacy-head a.list-remove,
+#privacy .privacy-item a.item-remove {
+       background-position: 2px -1197px;
+}
+
+#privacy .privacy-item a.item-save {
+       background-position: 3px -126px;
+       width: auto;
+       height: 19px;
+       padding: 1px 7px 0 21px;
+}
+
+#privacy .privacy-item,
+#privacy form,
+#privacy .privacy-active {
+       clear: both;
+}
+
+#privacy .privacy-item {
+       margin: 17px 12px;
+       font-size: 0.9em;
+}
+
+#privacy .privacy-item span {
+       font-weight: bold;
+}
+
+#privacy .privacy-item select {
+       width: 300px;
+       margin: -4px 30px 0 10px;
+}
+
+#privacy .privacy-item a {
+       margin: -2px 6px 0 0;
+}
+
+#privacy .privacy-first,
+#privacy .privacy-second,
+#privacy .privacy-third {
+       height: 195px;
+       font-size: 0.9em;
+       margin: 10px 0 0 10px;
+       float: left;
+}
+
+#privacy .privacy-first,
+#privacy .privacy-second {
+       border-right: 1px dotted #1b393f;
+       padding-right: 14px;
+}
+
+#privacy .privacy-first {
+       width: 125px;
+}
+
+#privacy .privacy-first label {
+       margin: 50px 0 0 15px;
+}
+
+#privacy .privacy-first label input {
+       margin-top: 2px;
+}
+
+#privacy .privacy-second {
+       width: 205px;
+}
+
+#privacy .privacy-second label {
+       margin: 2px 0 0 12px;
+}
+
+#privacy .privacy-second input[type=radio],
+#privacy .privacy-third input[type=checkbox] {
+       margin-top: 2px;
+       margin-bottom: 2px;
+}
+
+#privacy .privacy-second input[type=text],
+#privacy .privacy-second select {
+       width: 170px;
+       margin: 2px 0 11px 12px;
+       float: none;
+}
+
+#privacy .privacy-third label {
+       width: auto;
+       margin-top: 11px;
+}
+
+#privacy .privacy-third {
+       width: 240px;
+}
+
+#privacy .privacy-active {
+       margin: 34px 16px 0 16px;
+       font-size: 0.9em;
+}
+
+#privacy .privacy-active-elements {
+       float: right;
+}
+
+#privacy .privacy-active input[type=text] {
+       width: 30px;
+       margin: 0 0 0 8px;
+       float: none;
+}
+
+#privacy .privacy-active input[type=checkbox] {
+       margin: 2px 8px 0 0;
+       float: left;
+}
+
+#privacy .privacy-active label {
+       width: auto;
+       margin: 0 15px 0 0;
+       clear: none;
+}
diff --git a/jappixmini/jappix/css/rosterx.css b/jappixmini/jappix/css/rosterx.css
new file mode 100644 (file)
index 0000000..4f159ac
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+
+Jappix - An open social platform
+This is the Roster Item Exchange tool CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 05/02/11
+
+*/
+
+#rosterx .content {
+       padding: 10px 0 10px 0;
+}
+
+#rosterx .rosterx-head a {
+       font-size: 0.9em;
+       margin: 3px 4px;
+       float: left;
+}
+
+#rosterx .oneresult:hover {
+       cursor: pointer;
+}
+
+#rosterx .oneresult span {
+       margin: 2px 5px 0 5px;
+       overflow: hidden;
+       float: left;
+}
+
+#rosterx .oneresult span.name {
+       width: 230px;
+       font-weight: bold;
+}
+
+#rosterx .oneresult span.xid {
+       width: 270px;
+       font-size: 0.9em;
+}
+
+#rosterx .oneresult span.action {
+       width: 16px;
+       height: 16px;
+       margin-top: 4px;
+       float: right;
+}
+
+#rosterx .oneresult span.action.modify {
+       background-position: 0 -1244px;
+}
diff --git a/jappixmini/jappix/css/search.css b/jappixmini/jappix/css/search.css
new file mode 100644 (file)
index 0000000..505b17d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+
+Jappix - An open social platform
+This is the search tool CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/01/11
+
+*/
+
+.search {
+       position: relative;
+}
+
+.search input.suggested {
+       border-bottom: 1px solid white;
+       border-bottom-right-radius: 0;
+       border-bottom-left-radius: 0;
+       -moz-border-radius-bottomright: 0;
+       -moz-border-radius-bottomleft: 0;
+       -webkit-border-bottom-right-radius: 0;
+       -webkit-border-bottom-left-radius: 0;
+}
+
+.search ul {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.9);
+       border-color: #e1a014;
+       border-style: solid;
+       border-width: 0 1px 1px 1px;
+       position: absolute;
+       z-index: 1;
+       padding: 3px 0;
+       list-style: none;
+       overflow: auto;
+       border-bottom-right-radius: 3px;
+       border-bottom-left-radius: 3px;
+       -moz-border-radius-bottomright: 3px;
+       -moz-border-radius-bottomleft: 3px;
+       -webkit-border-bottom-right-radius: 3px;
+       -webkit-border-bottom-left-radius: 3px;
+}
+
+.search ul li {
+       padding: 2px 6px;
+       color: #3d3d3d;
+       text-shadow: none;
+}
+
+.search ul li:hover {
+       cursor: pointer;
+}
+
+.search ul li.hovered {
+       background-color: rgb(225,160,20);
+       background-color: rgba(225,160,20,0.3);
+}
diff --git a/jappixmini/jappix/css/smileys.css b/jappixmini/jappix/css/smileys.css
new file mode 100644 (file)
index 0000000..faad478
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+
+Jappix - An open social platform
+This is the smileys CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/02/11
+
+*/
+
+.emoticon {
+       width: 16px;
+       height: 16px;
+}
+
+a.emoticon {
+       margin: 2px;
+       float: left;
+}
+
+a.emoticon:hover,
+a.emoticon:focus {
+       opacity: 0.8;
+}
+
+a.emoticon:active {
+       opacity: 0.7;
+}
+
+img.emoticon {
+       border: 0 none;
+       vertical-align: bottom;
+}
+
+.emoticon-biggrin {
+       background-position: 0 0;
+}
+
+.emoticon-devil {
+       background-position: -16px 0;
+}
+
+.emoticon-coolglasses {
+       background-position: -32px 0;
+}
+
+.emoticon-tongue {
+       background-position: -48px 0;
+}
+
+.emoticon-smile {
+       background-position: -64px 0;
+}
+
+.emoticon-wink {
+       background-position: -80px 0;
+}
+
+.emoticon-blush {
+       background-position: -96px 0;
+}
+
+.emoticon-stare {
+       background-position: -112px 0;
+}
+
+.emoticon-frowning {
+       background-position: -128px 0;
+}
+
+.emoticon-oh {
+       background-position: -144px 0;
+}
+
+.emoticon-unhappy {
+       background-position: -160px 0;
+}
+
+.emoticon-cry {
+       background-position: -176px 0;
+}
+
+.emoticon-angry {
+       background-position: -192px 0;
+}
+
+.emoticon-puke {
+       background-position: -208px 0;
+}
+
+.emoticon-hugright {
+       background-position: -224px 0;
+}
+
+.emoticon-hugleft {
+       background-position: -240px 0;
+}
+
+.emoticon-lion {
+       background-position: -256px 0;
+}
+
+.emoticon-pussy {
+       background-position: -272px 0;
+}
+
+.emoticon-bat {
+       background-position: -288px 0;
+}
+
+.emoticon-kiss {
+       background-position: -304px 0;
+}
+
+.emoticon-heart {
+       background-position: -320px 0;
+}
+
+.emoticon-brheart {
+       background-position: -336px 0;
+}
+
+.emoticon-flower {
+       background-position: -352px 0;
+}
+
+.emoticon-brflower {
+       background-position: -368px 0;
+}
+
+.emoticon-thumbup {
+       background-position: -384px 0;
+}
+
+.emoticon-thumbdown {
+       background-position: -400px 0;
+}
+
+.emoticon-lamp {
+       background-position: -416px 0;
+}
+
+.emoticon-coffee {
+       background-position: -432px 0;
+}
+
+.emoticon-drink {
+       background-position: -448px 0;
+}
+
+.emoticon-beer {
+       background-position: -464px 0;
+}
+
+.emoticon-boy {
+       background-position: -480px 0;
+}
+
+.emoticon-girl {
+       background-position: -496px 0;
+}
+
+.emoticon-phone {
+       background-position: -512px 0;
+}
+
+.emoticon-photo {
+       background-position: -528px 0;
+}
+
+.emoticon-music {
+       background-position: -544px 0;
+}
+
+.emoticon-cuffs {
+       background-position: -560px 0;
+}
+
+.emoticon-mail {
+       background-position: -576px 0;
+}
+
+.emoticon-rainbow {
+       background-position: -592px 0;
+}
+
+.emoticon-star {
+       background-position: -608px 0;
+}
+
+.emoticon-moon {
+       background-position: -624px 0;
+}
diff --git a/jappixmini/jappix/css/stats-svg.css b/jappixmini/jappix/css/stats-svg.css
new file mode 100644 (file)
index 0000000..f512a93
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+
+Jappix - An open social platform
+This is the SVG stats CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Erwan Briand, Vanaryon
+Last revision: 20/11/10
+
+*/
+
+svg {
+       background-color: #e8f1f3;
+}
+
+.refline {
+    stroke: #596171;
+    stroke-width: 2px;
+}
+
+.refleft {
+    fill: #000000;
+    font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif;
+    font-size: 8px;
+}
+
+.reftext {
+    fill: #586070;
+    font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif;
+    font-size: 10px;
+}
+
+.bubbletextblue,
+.bubbletextred {
+    fill: none;
+    font-family: "Inconsolata", "DejaVu Serif sans", Verdana, sans-serif;
+    font-size: 8px;
+    text-anchor: end;
+}
+
+.bluebar {
+    fill: "#6C84C0";
+    fill-opacity: "0.6";
+}
+
+.gbar:hover .bluebar {
+    fill: #2A3F73;
+}
+
+.gbar:hover .redbar {
+    fill: #C70705;
+}
+
+.gbar:hover #bubble {
+    fill: white;
+    stroke: grey;
+}
+
+.gbar:hover .bubbletextblue {
+    fill: #2A3F73;
+}
+
+.gbar:hover .bubbletextred {
+    fill: #C70705;
+}
+
+.gbar:hover .reftext {
+    fill: #000000;
+}
diff --git a/jappixmini/jappix/css/tools.css b/jappixmini/jappix/css/tools.css
new file mode 100644 (file)
index 0000000..8b689f5
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+
+Jappix - An open social platform
+This is the tools CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+#top-content .tools {
+       background-color: rgb(232,241,243);
+       background-color: rgba(232,241,243,0.6);
+       padding: 3px 8px 5px 8px;
+       min-width: 10px;
+       height: 17px;
+       border-bottom-left-radius: 4px;
+       border-bottom-right-radius: 4px;
+       -moz-border-radius-bottomleft: 4px;
+       -moz-border-radius-bottomright: 4px;
+       -webkit-border-bottom-left-radius: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+}
+
+#top-content .tools a {
+       color: black;
+       padding: 0 3px;
+       margin: 0 1.5px;
+}
+
+#top-content .tools a:hover,
+#top-content .tools a:focus {
+       cursor: pointer;
+       text-decoration: underline;
+}
+
+#top-content .tools-logo {
+       background-position: 9px 2px;
+       width: 74px;
+       float: left;
+}
+
+#top-content .tools-all {
+       float: right;
+       text-align: right;
+       margin-left: 8px;
+       font-size: 0.9em;
+       color: black;
+}
+
+#top-content .notifications {
+       background-position: 7px -1264px;
+}
+
+#top-content .music {
+       background-position: 6px -1286px;
+}
+
+#top-content .notifications:hover,
+#top-content .music:hover {
+       cursor: pointer;
+}
+
+#top-content .music:hover,
+#top-content .notifications:hover,
+#top-content .music:focus,
+#top-content .notifications:focus {
+       background-color: rgb(232,241,243);
+       background-color: rgba(232,241,243,0.7);
+}
+
+#top-content .music:active,
+#top-content .notifications:active {
+       background-color: rgb(232,241,243);
+       background-color: rgba(232,241,243,0.8);
+}
+
+#top-content .actived,
+#top-content .actived:hover,
+#top-content .actived:focus,
+#top-content .actived:active {
+       background-color: rgb(232,241,243) !important;
+       background-color: rgba(232,241,243,0.9) !important;
+}
+
+#top-content .notify {
+       background-color: #c60505;
+       color: white;
+       font-size: 0.7em;
+       font-weight: bold;
+       margin-left: -10px;
+       padding: 1px 4px;
+       position: absolute;
+       bottom: -2px;
+       border-radius: 10px;
+       -moz-border-radius: 10px;
+       -webkit-border-radius: 10px;
+}
+
+#top-content .tools-content {
+       display: none;
+       position: absolute;
+       top: 25px;
+       margin-left: -8px;
+}
+
+.tools-content-subarrow {
+       background-position: 0 -241px;
+       opacity: 0.8;
+       height: 10px;
+       width: 18px;
+       margin-left: 12px;
+}
+
+.tools-content-subitem {
+       background-color: rgb(0,0,0);
+       background-color: rgba(0,0,0,0.8);
+       padding: 14px 6px 6px 6px;
+       border-radius: 5px;
+       -moz-border-radius: 5px;
+       -webkit-border-radius: 5px;
+}
+
+.notifications-content {
+       width: 240px;
+}
+
+.notifications-content .tools-content-subitem {
+       max-height: 250px;
+       color: white;
+       text-shadow: 0 1px 1px black;
+       text-align: left;
+       overflow-x: none;
+       overflow-y: auto;
+}
+
+.notifications-content .empty {
+       color: white;
+       font-size: 0.9em;
+       text-decoration: underline;
+       margin: -8px 4px 2px 0;
+       display: none;
+       float: right;
+}
+
+.notifications-content .nothing {
+       font-size: 0.9em;
+       margin: 5px;
+}
+
+.notifications-content .one-notification {
+       padding: 6px 4px;
+       font-size: 0.85em;
+       clear: both;
+       border-radius: 2px;
+       -moz-border-radius: 2px;
+       -webkit-border-radius: 2px;
+}
+
+.notifications-content .one-notification:hover,
+.notifications-content .one-notification:focus {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.1);
+}
+
+.notifications-content .one-notification:active {
+       background-color: rgb(255,255,255);
+       background-color: rgba(255,255,255,0.2);
+}
+
+.notifications-content .avatar-container {
+       float: left;
+       width: 40px;
+       height: 40px;
+       margin: 0 8px 8px 0;
+       text-align: center;
+       background-repeat: no-repeat;
+}
+
+.notifications-content .avatar {
+       max-width: 40px;
+       max-height: 40px;
+}
+
+.notifications-content .notification-text,
+.notifications-content .notification-actions {
+       margin-left: 48px;
+       overflow: hidden;
+}
+
+.notifications-content .notification-actions {
+       margin-top: 3px;
+}
+
+.notifications-content .notification-actions a {
+       color: white;
+       font-weight: bold;
+       font-size: 0.9em;
+       text-decoration: underline;
+       margin-right: 8px;
+}
+
+.notifications-content .one-notification .notification-actions span.talk-images {
+       background-position: 0 -1828px;
+       width: 16px;
+       height: 16px;
+       margin: -1px 6px 0 0;
+       float: left;
+}
+
+.notifications-content .one-notification[data-type=subscribe] .notification-actions span.talk-images {
+       background-position: 0 -1796px;
+}
+
+.notifications-content .one-notification[data-type=invite_room] .notification-actions span.talk-images {
+       background-position: 0 -1812px;
+}
+
+.notifications-content .one-notification[data-type=send] .notification-actions span.talk-images,
+.notifications-content .one-notification[data-type=send_accept] .notification-actions span.talk-images,
+.notifications-content .one-notification[data-type=send_reject] .notification-actions span.talk-images,
+.notifications-content .one-notification[data-type=send_fail] .notification-actions span.talk-images {
+       background-position: 0 -1956px;
+}
+
+.notifications-content .one-notification[data-type=rosterx] .notification-actions span.talk-images {
+       background-position: 0 -1844px;
+}
+
+.notifications-content .one-notification[data-type=comment] .notification-actions span.talk-images {
+       background-position: 0 -1860px;
+}
+
+.notifications-content .one-notification[data-type=like] .notification-actions span.talk-images {
+       background-position: 0 -1876px;
+}
+
+.notifications-content .one-notification[data-type=quote] .notification-actions span.talk-images {
+       background-position: 0 -1892px;
+}
+
+.notifications-content .one-notification[data-type=wall] .notification-actions span.talk-images {
+       background-position: 0 -1908px;
+}
+
+.notifications-content .one-notification[data-type=photo] .notification-actions span.talk-images {
+       background-position: 0 -1924px;
+}
+
+.notifications-content .one-notification[data-type=video] .notification-actions span.talk-images {
+       background-position: 0 -1940px;
+}
+
+.music-content {
+       width: 220px;
+}
+
+.music-content .tools-content-subitem {
+       height: 247px;
+}
+
+.music-content .player {
+       background: #b5d5db;
+       background: -moz-linear-gradient(top, #b5d5db, #adced4);
+       background: -webkit-gradient(linear, left top, left bottom, from(#b5d5db), to(#adced4));
+       height: 20px;
+       padding: 2px 5px;
+       border-top-right-radius: 4px;
+       border-top-left-radius: 4px;
+       -moz-border-radius-topright: 4px;
+       -moz-border-radius-topleft: 4px;
+       -webkit-border-top-right-radius: 4px;
+       -webkit-border-top-left-radius: 4px;
+}
+
+.music-content .player a {
+       margin: 2px;
+       height: 16px;
+       width: 16px;
+       float: left;
+}
+
+.music-content .player a:hover,
+.music-content .player a:focus {
+       opacity: 0.8;
+}
+
+.music-content .player a:active {
+       opacity: 0.6;
+}
+
+.music-content .stop {
+       display: none;
+       background-position: 0 -270px;
+}
+
+.music-content .list {
+       background-color: #e8f1f3;
+       height: 188px;
+       padding: 5px;
+       text-align: left;
+       overflow-y: auto;
+       overflow-x: hidden;
+}
+
+.music-content p.no-results {
+       display: none;
+       color: black;
+       font-size: 0.9em;
+}
+
+.music-content div.special {
+       padding-bottom: 2px;
+       margin-bottom: 6px;
+       border-bottom: 1px solid #c3d4d7;
+}
+
+.music-content .song {
+       display: block;
+       margin: 3px 0;
+       font-size: 0.8em;
+}
+
+.music-content .playing {
+       font-weight: bold;
+}
+
+.music-content .search {
+       background-color: #e8f1f3;
+       height: 25px;
+       border-bottom-left-radius: 4px;
+       border-bottom-right-radius: 4px;
+       -moz-border-radius-bottomleft: 4px;
+       -moz-border-radius-bottomright: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+       -webkit-border-bottom-right-radius: 4px;
+}
+
+.music-content .search input {
+       margin: 2px;
+       width: 198px;
+       height: 15px;
+}
diff --git a/jappixmini/jappix/css/userinfos.css b/jappixmini/jappix/css/userinfos.css
new file mode 100644 (file)
index 0000000..59bab65
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+
+Jappix - An open social platform
+This is the user-infos CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/03/11
+
+*/
+
+#userinfos .content {
+       overflow: auto;
+}
+
+#userinfos .one-lap a {
+       text-decoration: underline;
+}
+
+#userinfos .main-infos {
+       margin: 20px 20px 8px 20px;
+       height: 120px;
+       background: white;
+       position: relative;
+       border-radius: 4px;
+       -moz-border-radius: 4px;
+       -webkit-border-radius: 4px;
+}
+
+#userinfos .avatar-container {
+       float: left;
+       text-align: center;
+       margin: 20px 35px;
+       width: 80px;
+       height: 80px;
+}
+
+#userinfos .avatar {
+       max-width: 80px;
+       max-height: 80px;
+}
+
+#userinfos h1,
+#userinfos h2,
+#userinfos h3 {
+       width: 410px;
+       overflow: hidden;
+}
+
+#userinfos h1 {
+       font-size: 2em;
+       padding-top: 12px;
+       margin-bottom: 4px;
+}
+
+#userinfos h2 {
+       color: #447079;
+       font-size: 1.1em;
+       margin-bottom: 10px;
+}
+
+#userinfos h3 {
+       color: #6e8388;
+       font-size: 0.8em;
+}
+
+#userinfos .main-infos div.shortcuts {
+       position: absolute;
+       top: 10px;
+       right: 12px;
+}
+
+#userinfos .block-infos {
+       margin: 7px 20px;
+       float: left;
+}
+
+#userinfos .one-line {
+       margin: 4px 0;
+       font-size: 0.9em;
+       float: left;
+}
+
+#userinfos .one-line b {
+       width: 120px;
+       float: left;
+}
+
+#userinfos .one-line span.reset-info {
+       float: left;
+       width: 460px;
+}
+
+#userinfos textarea {
+       margin: 30px 0 0 30px;
+       width: 572px;
+       height: 292px;
+}
diff --git a/jappixmini/jappix/css/vcard.css b/jappixmini/jappix/css/vcard.css
new file mode 100644 (file)
index 0000000..59dfc48
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+
+Jappix - An open social platform
+This is the vCard CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+#vcard label {
+       font-size: 0.94em;
+       margin-top: 2px;
+}
+
+#vcard #vcard-avatar input[type=file] {
+       margin-left: 15px;
+}
+
+#vcard .avatar-container {
+       float: left;
+       text-align: center;
+       margin: 20px 0 35px 35px;
+       max-width: 96px;
+       max-height: 96px;
+}
+
+#vcard .avatar {
+       max-width: 96px;
+       max-height: 96px;
+}
+
+#vcard .avatar-delete {
+       background-position: 3px -1195px;
+       margin: 12px 25px 0 025px;
+       padding-left: 20px;
+       font-size: 0.9em;
+       float: right;
+}
+
+#vcard .no-avatar {
+       width: 300px;
+       color: #7c2222;
+       padding: 10px;
+       margin: 15px 0 20px 40px;
+       background: #f8cece;
+       border: 1px #ba6d6d solid;
+       font-size: 0.8em;
+}
+
+#vcard .forms textarea {
+       height: 111px;
+       width: 358px;
+       margin: 5px 12px 10px 12px;
+}
+
+#vcard .forms .avatar-info {
+       border-width: 1px;
+       border-style: solid;
+       display: none;
+       width: 370px;
+       height: 15px;
+       font-size: 0.85em;
+       padding: 10px;
+}
+
+#vcard .forms .avatar-wait {
+       background-color: #9bcbed;
+       color: #0a3858;
+       border-color: #306780;
+}
+
+#vcard .forms .avatar-ok {
+       background-color: #c4ed9b;
+       color: #325213;
+       border-color: #578030;
+}
+
+#vcard .forms .avatar-error {
+       background-color: #e79595;
+       color: #6a0b0b;
+       border-color: #7c1010;
+}
+
+#vcard .infos {
+       width: 179px;
+       height: 328px;
+       margin: 15px 15px 15px 0;
+       padding: 0 8px;
+       float: right;
+}
+
+#vcard .infos a {
+       text-decoration: underline;
+}
+
+#vcard .send {
+       float: right;
+}
+
+#vcard .send:hover {
+       cursor: pointer;
+}
diff --git a/jappixmini/jappix/css/welcome.css b/jappixmini/jappix/css/welcome.css
new file mode 100644 (file)
index 0000000..71b31ef
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+
+Jappix - An open social platform
+This is the welcome tool CSS stylesheet for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/04/11
+
+*/
+
+#welcome .infos {
+       margin: 15px;
+}
+
+#welcome .infos p {
+       margin-top: 6px;
+}
+
+#welcome .infos p.infos-title {
+       margin-top: 0;
+}
+
+#welcome a.box {
+       background-color: #e4eef9;
+       border: 1px solid #ccdbde;
+       margin: 12px 11px 4px 15px;
+       padding: 10px;
+       width: 270px;
+       text-decoration: none;
+       float: left;
+       border-radius: 4px;
+       -moz-border-radius: 4px;
+       -webkit-border-radius: 4px;
+}
+
+#welcome a.box.share {
+       width: 350px;
+       margin: 4px 130px;
+       padding: 4px 10px;
+       clear: both;
+}
+
+#welcome a.box.share.first {
+       margin-top: 0;
+}
+
+#welcome a.box.share:hover span.go {
+       display: block;
+}
+
+#welcome a.box:hover,
+#welcome a.box:focus {
+       border: 1px solid #93c5fa;
+}
+
+#welcome a.box:active {
+       border: 1px solid #419afa;
+}
+
+#welcome a.box.enabled {
+       background-color: #f1f6fd;
+       border: 1px solid #9dc4fc;
+}
+
+#welcome a.box span {
+       margin: 3px 0;
+       display: block;
+}
+
+#welcome a.box span.logo {
+       height: 35px;
+       width: 35px;
+       margin-right: 15px;
+       float: left;
+}
+
+#welcome a.box span.logo.facebook {
+       background-position: 0 0;
+}
+
+#welcome a.box span.logo.twitter {
+       background-position: -35px 0;
+}
+
+#welcome a.box span.logo.buzz {
+       background-position: -70px 0;
+}
+
+#welcome a.box span.logo.identica {
+       background-position: -105px 0;
+}
+
+#welcome a.box span.option,
+#welcome a.box span.name {
+       font-size: 0.9em;
+       font-weight: bold;
+}
+
+#welcome a.box span.description {
+       font-size: 0.7em;
+       margin-top: 7px;
+}
+
+#welcome a.box.share span.description {
+       margin-top: 4px;
+}
+
+#welcome a.box span.image {
+       height: 16px;
+       width: 16px;
+       margin: -30px 12px 0 0;
+       float: right;
+}
+
+#welcome a.box span.image.sound {
+       background-position: 0 -900px;
+}
+
+#welcome a.box span.image.geolocation {
+       background-position: 0 -658px;
+}
+
+#welcome a.box span.image.xmpp {
+       background-position: 0 -990px;
+}
+
+#welcome a.box span.image.archives,
+#page-engine .text .tools-archives {
+       background-position: 0 -1025px;
+}
+
+#welcome a.box span.image.offline {
+       background-position: 0 -80px;
+}
+
+#welcome a.box span.tick,
+#welcome a.box span.go {
+       height: 16px;
+       width: 16px;
+       display: none;
+       float: right;
+}
+
+#welcome a.box span.tick {
+       background-position: 0 -1661px;
+       margin: -52px -15px 0 0;
+}
+
+#welcome a.box span.go {
+       background-position: 0 -1120px;
+       margin: -28px 5px 0 0;
+}
+
+#welcome a.box.enabled span.tick {
+       display: block;
+}
+
+#welcome div.results {
+       margin: -7px 15px;
+       padding: 0;
+       height: 272px;
+       overflow: auto;
+}
+
+#welcome .bottom .finish.save {
+       display: none;
+}
diff --git a/jappixmini/jappix/favicon.ico b/jappixmini/jappix/favicon.ico
new file mode 100644 (file)
index 0000000..dc20377
Binary files /dev/null and b/jappixmini/jappix/favicon.ico differ
diff --git a/jappixmini/jappix/img/others/blank.gif b/jappixmini/jappix/img/others/blank.gif
new file mode 100644 (file)
index 0000000..35d42e8
Binary files /dev/null and b/jappixmini/jappix/img/others/blank.gif differ
diff --git a/jappixmini/jappix/img/others/default-avatar.png b/jappixmini/jappix/img/others/default-avatar.png
new file mode 100644 (file)
index 0000000..7cda4c6
Binary files /dev/null and b/jappixmini/jappix/img/others/default-avatar.png differ
diff --git a/jappixmini/jappix/img/others/lock.png b/jappixmini/jappix/img/others/lock.png
new file mode 100644 (file)
index 0000000..cba6c0d
Binary files /dev/null and b/jappixmini/jappix/img/others/lock.png differ
diff --git a/jappixmini/jappix/img/sprites/animate.gif b/jappixmini/jappix/img/sprites/animate.gif
new file mode 100644 (file)
index 0000000..cbf55da
Binary files /dev/null and b/jappixmini/jappix/img/sprites/animate.gif differ
diff --git a/jappixmini/jappix/img/sprites/animate.png b/jappixmini/jappix/img/sprites/animate.png
new file mode 100644 (file)
index 0000000..3d89e5d
Binary files /dev/null and b/jappixmini/jappix/img/sprites/animate.png differ
diff --git a/jappixmini/jappix/img/sprites/background.png b/jappixmini/jappix/img/sprites/background.png
new file mode 100644 (file)
index 0000000..4ae286d
Binary files /dev/null and b/jappixmini/jappix/img/sprites/background.png differ
diff --git a/jappixmini/jappix/img/sprites/browsers.png b/jappixmini/jappix/img/sprites/browsers.png
new file mode 100644 (file)
index 0000000..8fadb7b
Binary files /dev/null and b/jappixmini/jappix/img/sprites/browsers.png differ
diff --git a/jappixmini/jappix/img/sprites/buttons.png b/jappixmini/jappix/img/sprites/buttons.png
new file mode 100644 (file)
index 0000000..4c32b14
Binary files /dev/null and b/jappixmini/jappix/img/sprites/buttons.png differ
diff --git a/jappixmini/jappix/img/sprites/home.png b/jappixmini/jappix/img/sprites/home.png
new file mode 100644 (file)
index 0000000..cd3ca4a
Binary files /dev/null and b/jappixmini/jappix/img/sprites/home.png differ
diff --git a/jappixmini/jappix/img/sprites/install.png b/jappixmini/jappix/img/sprites/install.png
new file mode 100644 (file)
index 0000000..e2f4cd2
Binary files /dev/null and b/jappixmini/jappix/img/sprites/install.png differ
diff --git a/jappixmini/jappix/img/sprites/logs.png b/jappixmini/jappix/img/sprites/logs.png
new file mode 100644 (file)
index 0000000..db99a20
Binary files /dev/null and b/jappixmini/jappix/img/sprites/logs.png differ
diff --git a/jappixmini/jappix/img/sprites/manager.png b/jappixmini/jappix/img/sprites/manager.png
new file mode 100644 (file)
index 0000000..d63a3fe
Binary files /dev/null and b/jappixmini/jappix/img/sprites/manager.png differ
diff --git a/jappixmini/jappix/img/sprites/me.png b/jappixmini/jappix/img/sprites/me.png
new file mode 100644 (file)
index 0000000..8a8bc0f
Binary files /dev/null and b/jappixmini/jappix/img/sprites/me.png differ
diff --git a/jappixmini/jappix/img/sprites/mini.gif b/jappixmini/jappix/img/sprites/mini.gif
new file mode 100644 (file)
index 0000000..661abaf
Binary files /dev/null and b/jappixmini/jappix/img/sprites/mini.gif differ
diff --git a/jappixmini/jappix/img/sprites/mini.png b/jappixmini/jappix/img/sprites/mini.png
new file mode 100644 (file)
index 0000000..83cedc4
Binary files /dev/null and b/jappixmini/jappix/img/sprites/mini.png differ
diff --git a/jappixmini/jappix/img/sprites/mobile.png b/jappixmini/jappix/img/sprites/mobile.png
new file mode 100644 (file)
index 0000000..2e5a16a
Binary files /dev/null and b/jappixmini/jappix/img/sprites/mobile.png differ
diff --git a/jappixmini/jappix/img/sprites/smileys.png b/jappixmini/jappix/img/sprites/smileys.png
new file mode 100644 (file)
index 0000000..1c33243
Binary files /dev/null and b/jappixmini/jappix/img/sprites/smileys.png differ
diff --git a/jappixmini/jappix/img/sprites/talk.png b/jappixmini/jappix/img/sprites/talk.png
new file mode 100644 (file)
index 0000000..a307e19
Binary files /dev/null and b/jappixmini/jappix/img/sprites/talk.png differ
diff --git a/jappixmini/jappix/img/sprites/welcome.png b/jappixmini/jappix/img/sprites/welcome.png
new file mode 100644 (file)
index 0000000..9044bd9
Binary files /dev/null and b/jappixmini/jappix/img/sprites/welcome.png differ
diff --git a/jappixmini/jappix/img/wait/wait-big.gif b/jappixmini/jappix/img/wait/wait-big.gif
new file mode 100644 (file)
index 0000000..c657320
Binary files /dev/null and b/jappixmini/jappix/img/wait/wait-big.gif differ
diff --git a/jappixmini/jappix/img/wait/wait-medium.png b/jappixmini/jappix/img/wait/wait-medium.png
new file mode 100644 (file)
index 0000000..4b9a780
Binary files /dev/null and b/jappixmini/jappix/img/wait/wait-medium.png differ
diff --git a/jappixmini/jappix/img/wait/wait-small.gif b/jappixmini/jappix/img/wait/wait-small.gif
new file mode 100644 (file)
index 0000000..c4b5787
Binary files /dev/null and b/jappixmini/jappix/img/wait/wait-small.gif differ
diff --git a/jappixmini/jappix/js/adhoc.js b/jappixmini/jappix/js/adhoc.js
new file mode 100644 (file)
index 0000000..d4e3bf4
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+
+Jappix - An open social platform
+These are the Ad-Hoc JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 11/07/11
+
+*/
+
+// Opens the adhoc popup
+function openAdHoc() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Commands") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="adhoc-head"></div>' + 
+               
+               '<div class="results adhoc-results"></div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('adhoc', html);
+       
+       // Associate the events
+       launchAdHoc();
+       
+       return false;
+}
+
+// Quits the adhoc popup
+function closeAdHoc() {
+       // Destroy the popup
+       destroyPopup('adhoc');
+       
+       return false;
+}
+
+// Retrieves an entity adhoc command
+function retrieveAdHoc(xid) {
+       // Open the popup
+       openAdHoc();
+       
+       // Add a XID marker
+       $('#adhoc .adhoc-head').html('<b>' + getBuddyName(xid).htmlEnc() + '</b> (' + xid.htmlEnc() + ')');
+       
+       // Get the highest entity resource
+       var highest = getHighestResource(xid);
+       
+       if(highest)
+               xid = highest;
+       
+       // Start a new adhoc command
+       dataForm(xid, 'command', '', '', 'adhoc');
+       
+       return false;
+}
+
+// Starts an adhoc command on the user server
+function serverAdHoc(server) {
+       // Open the popup
+       openAdHoc();
+       
+       // Add a XID marker
+       $('#adhoc .adhoc-head').html('<b>' + server.htmlEnc() + '</b>');
+       
+       // Start a new adhoc command
+       dataForm(server, 'command', '', '', 'adhoc');
+}
+
+// Plugin launcher
+function launchAdHoc() {
+       // Click event
+       $('#adhoc .bottom .finish').click(closeAdHoc);
+}
diff --git a/jappixmini/jappix/js/anonymous.js b/jappixmini/jappix/js/anonymous.js
new file mode 100644 (file)
index 0000000..88eaa7d
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+
+Jappix - An open social platform
+These are the anonymous mode JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, LinkMauve
+Last revision: 02/10/11
+
+*/
+
+// Connected to an anonymous session
+function anonymousConnected(con) {
+       logThis('Jappix (anonymous) is now connected.', 3);
+       
+       // Connected marker
+       CONNECTED = true;
+       CURRENT_SESSION = true;
+       RECONNECT_TRY = 0;
+       RECONNECT_TIMER = 0;
+       
+       // Not resumed?
+       if(!RESUME) {
+               // Create the app
+               createTalkPage();
+               
+               // Send our first presence
+               firstPresence('');
+               
+               // Set last activity stamp
+               LAST_ACTIVITY = getTimeStamp();
+               
+               // Create the new groupchat
+               checkChatCreate(generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat');
+               
+               // Remove some nasty elements for the anonymous mode
+               $('.tools-mucadmin, .tools-add').remove();
+       }
+       
+       // Resumed
+       else {
+               // Send again our presence
+               presenceSend();
+               
+               // Change the title
+               updateTitle();
+       }
+       
+       // Remove the waiting icon
+       removeGeneralWait();
+}
+
+// Disconnected from an anonymous session
+function anonymousDisconnected() {
+       logThis('Jappix (anonymous) is now disconnected.', 3);
+}
+
+// Logins to a anonymous account
+function anonymousLogin(server) {
+       try {
+               // We define the http binding parameters
+               oArgs = new Object();
+               
+               if(HOST_BOSH_MAIN)
+                       oArgs.httpbase = HOST_BOSH_MAIN;
+               else
+                       oArgs.httpbase = HOST_BOSH;
+               
+               // We create the new http-binding connection
+               con = new JSJaCHttpBindingConnection(oArgs);
+               
+               // And we handle everything that happen
+               con.registerHandler('message', handleMessage);
+               con.registerHandler('presence', handlePresence);
+               con.registerHandler('iq', handleIQ);
+               con.registerHandler('onconnect', anonymousConnected);
+               con.registerHandler('onerror', handleError);
+               con.registerHandler('ondisconnect', anonymousDisconnected);
+               
+               // We set the anonymous connection parameters
+               oArgs = new Object();
+               oArgs.domain = server;
+               oArgs.authtype = 'saslanon';
+               oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')';
+               oArgs.secure = true;
+               oArgs.xmllang = XML_LANG;
+               
+               // We connect !
+               con.connect(oArgs);
+               
+               // Change the page title
+               pageTitle('wait');
+       }
+       
+       catch(e) {
+               // Logs errors
+               logThis('Error while anonymous loggin in: ' + e, 1);
+               
+               // Reset Jappix
+               anonymousDisconnected();
+               
+               // Open an unknown error
+               openThisError(2);
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+// Plugin launcher
+function launchAnonymous() {
+       logThis('Anonymous mode detected, connecting...', 3);
+       
+       // We add the login wait div
+       showGeneralWait();
+       
+       // Get the vars
+       if(LINK_VARS['r'])
+               ANONYMOUS_ROOM = LINK_VARS['r'];
+       if(LINK_VARS['n'])
+               ANONYMOUS_NICK = LINK_VARS['n'];
+       
+       // Fire the login action
+       anonymousLogin(HOST_ANONYMOUS);
+}
+
+// Launch this plugin!
+$(document).ready(launchAnonymous);
diff --git a/jappixmini/jappix/js/archives.js b/jappixmini/jappix/js/archives.js
new file mode 100644 (file)
index 0000000..387a379
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+
+Jappix - An open social platform
+These are the archives functions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/03/11
+
+*/
+
+// Opens the archive tools
+function openArchives() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Message archives") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="filter">' + 
+                       '<select class="friend" multiple=""></select>' + 
+                       
+                       '<div class="date"></div>' + 
+               '</div>' + 
+               
+               '<div class="current">' + 
+                       '<span class="name"></span>' + 
+                       '<span class="time">' + _e("Please select a friend to view the chat history.") + '</span>' + 
+               '</div>' + 
+               
+               '<div class="logs" id="chat-content-archives"></div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('archives', html);
+       
+       // Associate the events
+       launchArchives();
+       
+       // Get all the buddies in our roster
+       var buddies = getAllBuddies();
+       var options = '';
+       
+       for(i in buddies) {
+               var current = buddies[i];
+               
+               // Add the current buddy
+               options += '<option value="' + encodeQuotes(current) + '">' + getBuddyName(current).htmlEnc() + '</option>';
+       }
+       
+       // Can append the buddy HTML code?
+       if(options)
+               $('#archives .filter .friend').append(options);
+       
+       return false;
+}
+
+// Closes the archive tools
+function closeArchives() {
+       // Destroy the popup
+       destroyPopup('archives');
+       
+       return false;
+}
+
+// Gets the archives list for a buddy
+function getListArchives(xid) {
+       // Reset the archives viewer
+       $('#archives .logs').empty();
+       
+       // Show the waiting icon
+       $('#archives .wait').show();
+       
+       // Apply the ID
+       var id = genID();
+       $('#archives').attr('data-session', id);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setID(id);
+       
+       var list = iq.appendNode('list', {'xmlns': NS_URN_ARCHIVE, 'with': xid});
+       var set = list.appendChild(iq.buildNode('set', {'xmlns': NS_RSM}));
+       set.appendChild(iq.buildNode('max', {'xmlns': NS_RSM}, '0'));
+       
+       con.send(iq, handleListArchives);
+       
+       logThis('Getting archives list for: ' + xid + '...');
+}
+
+// Handles the archives list for a buddy
+function handleListArchives(iq) {
+       // Hide the waiting icon
+       $('#archives .wait').hide();
+       
+       // Any error?
+       if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']'))
+               return;
+       
+       // Get the last archive date
+       var last = $(iq.getNode()).find('list set changed').text();
+       
+       // Any last archive?
+       if(last) {
+               // Read the date
+               var date = Date.jab2date(last);
+               
+               // Change the datepicker value
+               $('#archives .filter .date').DatePickerSetDate(date, true);
+               
+               // Retrieve the archives
+               checkChangeArchives();
+       }
+       
+       logThis('Got archives list.', 2);
+}
+
+// Gets the archives for a day
+function getDayArchives(xid, date) {
+       // Reset the archives viewer
+       $('#archives .logs').empty();
+       
+       // Show the waiting icon
+       $('#archives .wait').show();
+       
+       // Apply the ID
+       var id = genID();
+       $('#archives').attr('data-session', id);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setID(id);
+       
+       iq.appendNode('list', {'xmlns': NS_URN_ARCHIVE, 'with': xid, 'start': date + 'T00:00:00Z', 'end': date + 'T23:59:59Z'});
+       
+       con.send(iq, handleDayArchives);
+       
+       logThis('Getting day archives (' + date + ') for: ' + xid + '...');
+}
+
+// Handles the archives for a day
+function handleDayArchives(iq) {
+       // Hide the waiting icon
+       $('#archives .wait').hide();
+       
+       // Any error?
+       if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']'))
+               return;
+       
+       // Get each archive thread
+       $(iq.getNode()).find('chat').each(function() {
+               // Current values
+               var xid = $(this).attr('with');
+               var start = $(this).attr('start');
+               
+               if(xid && start)
+                       $('#archives .logs').append('<input class="archives-pending" type="hidden" data-with="' + encodeQuotes(xid) + '" data-start="' + encodeQuotes(start) + '" />');
+       });
+       
+       // Display the day
+       var date = parseDay($('#archives .filter .date').DatePickerGetDate(true) + 'T00:00:00Z' + getDateTZO());
+       
+       // Try to get the first thread
+       var pending = '#archives input.archives-pending:first';
+       
+       if(!exists(pending))
+               date = printf(_e("Nothing found for: %s"), date);
+       
+       else {
+               retrieveArchives($(pending).attr('data-with'), $(pending).attr('data-start'));
+               $(pending).remove();
+       }
+       
+       $('#archives .current .time').text(date);
+       
+       logThis('Got day archives.', 2);
+}
+
+// Retrieves a specified archive collection
+function retrieveArchives(xid, start) {
+       // Show the waiting icon
+       $('#archives .wait').show();
+       
+       // Apply the ID
+       var id = genID();
+       $('#archives').attr('data-session', id);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setID(id);
+       
+       var list = iq.appendNode('retrieve', {'xmlns': NS_URN_ARCHIVE, 'with': xid, 'start': start});
+       
+       con.send(iq, handleRetrieveArchives);
+       
+       logThis('Retrieving archives (start: ' + start + ') for: ' + xid + '...');
+}
+
+// Handles a specified archive collection
+function handleRetrieveArchives(iq) {
+       // Hide the waiting icon
+       $('#archives .wait').hide();
+       
+       // Any error?
+       if(handleErrorReply(iq) || !exists('#archives[data-session=' + iq.getID() + ']'))
+               return;
+       
+       // Get the node
+       var chat = $(iq.getNode()).find('chat:first');
+       
+       // Get the buddy XID
+       var xid = bareXID(chat.attr('with'));
+       
+       // Get the start date & stamp
+       var start_date = Date.jab2date(chat.attr('start'));
+       var start_stamp = extractStamp(start_date);
+       
+       // Parse the result chat
+       chat.find('to, from').each(function() {
+               var node = (this).nodeName;
+               var stamp = start_stamp + parseInt($(this).attr('secs'));
+               var date = extractTime(new Date(stamp * 1000));
+               var body = $(this).find('body').text();
+               
+               // Is it my message?
+               if((node == 'to') && body)
+                       displayMessage('chat', getXID(), 'archives', getBuddyName(getXID()).htmlEnc(), body, date, start_stamp, 'user-message', true, '', 'me');
+               
+               // Is it a buddy message?
+               else if((node == 'from') && body)
+                       displayMessage('chat', xid, 'archives', getBuddyName(xid).htmlEnc(), body, date, start_stamp, 'user-message', true, '', 'him');
+       });
+       
+       // Not the latest thread?
+       var pending = '#archives input.archives-pending:first';
+       
+       if(exists(pending)) {
+               retrieveArchives($(pending).attr('data-with'), $(pending).attr('data-start'));
+               $(pending).remove();
+       }
+       
+       // Everything has been retrieved, get the avatars
+       else {
+               getAvatar(getXID(), 'cache', 'true', 'forget');
+               getAvatar(xid, 'cache', 'true', 'forget');
+       }
+       
+       logThis('Got archives.', 2);
+}
+
+// Gets the archiving configuration
+function getConfigArchives() {
+       // Lock the archiving options
+       $('#archiving').attr('checked', false).attr('disabled', true);
+       
+       // Get the archiving configuration
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE});
+       
+       con.send(iq, handleGetConfigArchives);
+}
+
+// Handles the archiving configuration
+function handleGetConfigArchives(iq) {
+       // Reset the options stuffs
+       waitOptions('archives');
+       
+       // Unlock the archiving options
+       $('#archiving').removeAttr('disabled');
+       
+       // End if not a result
+       if(!iq || (iq.getType() != 'result'))
+               return;
+       
+       // Extract the preferences from the IQ
+       var enabled = $(iq.getNode()).find('pref auto').attr('save');
+       
+       // Define the input enabling/disabling vars
+       var checked = true;
+       
+       if(enabled != 'true')
+               checked = false;
+       
+       // Apply the values
+       $('#archiving').attr('checked', checked);
+}
+
+// Configures the archiving on the server
+function configArchives(enabled) {
+       // Configure the auto element
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       iq.appendNode('auto', {'xmlns': NS_URN_ARCHIVE, 'save': enabled});
+       
+       con.send(iq, handleConfigArchives);
+       
+       // Configure the default element
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var pref = iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE});
+       pref.appendChild(iq.appendNode('default', {'xmlns': NS_URN_ARCHIVE, 'otr': 'concede', 'save': 'body'}));
+       
+       con.send(iq);
+       
+       // Configure the method element
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var mType = new Array('auto', 'local', 'manual');
+       var mUse = new Array('prefer', 'concede', 'concede');
+       
+       var pref = iq.appendNode('pref', {'xmlns': NS_URN_ARCHIVE});
+       
+       for(i in mType)
+               pref.appendChild(iq.appendNode('method', {'xmlns': NS_URN_ARCHIVE, 'type': mType[i], 'use': mUse[i]}));
+       
+       con.send(iq);
+       
+       // Logger
+       logThis('Configuring archives...', 3);
+}
+
+// Handles the archives configuration
+function handleConfigArchives(iq) {
+       if(!iq || (iq.getType() != 'result'))
+               logThis('Archives not configured.', 2);
+       else
+               logThis('Archives configured.', 3);
+}
+
+// Checks if the datepicker has changed
+function checkChangeArchives() {
+       var xid = $('#archives .filter .friend').val();
+       var date = $('#archives .filter .date').DatePickerGetDate(true);
+       
+       // No XID?
+       if(!xid || !xid.length)
+               return;
+       
+       // Too many value?
+       if(xid.length > 1) {
+               $('#archives .filter .friend').val(xid[0]);
+               
+               return;
+       }
+       
+       // Get the first XID
+       xid = xid[0];
+       
+       // Get the archives
+       getDayArchives(xid, date);
+}
+
+// Update the archives with the selected XID
+function updateArchives() {
+       // Read the values
+       var xid = $('#archives .filter .friend').val();
+       var date = $('#archives .filter .date').DatePickerGetDate(true);
+       
+       // No XID?
+       if(!xid || !xid.length)
+               return;
+       
+       // Too many value?
+       if(xid.length > 1) {
+               $('#archives .filter .friend').val(xid[0]);
+               
+               return;
+       }
+       
+       // Get the first XID
+       xid = xid[0];
+       
+       // Apply the current marker
+       $('#archives .current .name').text(getBuddyName(xid));
+       $('#archives .current .time').text(parseDay(date + 'T00:00:00Z' + getDateTZO()));
+       
+       // Get the archives
+       getListArchives(xid, date);
+}
+
+// Plugin launcher
+function launchArchives() {
+       // Current date
+       var current_date = explodeThis('T', getXMPPTime(), 0);
+       
+       // Datepicker
+       $('#archives .filter .date').DatePicker({
+               flat: true,
+               date: current_date,
+               current: current_date,
+               calendars: 1,
+               starts: 1,
+               onChange: checkChangeArchives
+       });
+       
+       // Click events
+       $('#archives .bottom .finish').click(function() {
+               return closeArchives();
+       });
+       
+       // Change event
+       $('#archives .filter .friend').change(updateArchives);
+}
diff --git a/jappixmini/jappix/js/audio.js b/jappixmini/jappix/js/audio.js
new file mode 100644 (file)
index 0000000..f83583a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+
+Jappix - An open social platform
+These are the audio JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 10/08/11
+
+*/
+
+// Plays the given sound ID
+function soundPlay(num) {
+       try {
+               // Not supported!
+               if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
+                       return false;
+               
+               // If the sounds are enabled
+               if(getDB('options', 'sounds') == '1') {
+                       // If the audio elements aren't yet in the DOM
+                       if(!exists('#audio')) {
+                               $('body').append(
+                                       '<div id="audio">' + 
+                                               '<audio id="new-chat" src="./snd/new-chat.oga" type="audio/ogg" />' + 
+                                               '<audio id="receive-message" src="./snd/receive-message.oga" type="audio/ogg" />' + 
+                                               '<audio id="notification" src="./snd/notification.oga" type="audio/ogg" />' + 
+                                       '</div>'
+                               );
+                       }
+                       
+                       // We play the target sound
+                       var playThis = document.getElementById('audio').getElementsByTagName('audio')[num];
+                       playThis.load();
+                       playThis.play();
+               }
+       }
+       
+       catch(e) {}
+       
+       finally {
+               return false;
+       }
+}
diff --git a/jappixmini/jappix/js/autocompletion.js b/jappixmini/jappix/js/autocompletion.js
new file mode 100644 (file)
index 0000000..52d3c47
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+
+Jappix - An open social platform
+These are the autocompletion tools JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 12/11/10
+
+*/
+
+// Sort an array with insensitivity to the case
+function caseInsensitiveSort(a, b) { 
+       // Put the two strings into lower case
+       a = a.toLowerCase();
+       b = b.toLowerCase();
+       
+       // Process the sort
+       if(a > b)
+               return 1;
+       if(a < b)
+               return -1;
+}
+
+// Creates an array with the autocompletion results
+function processAutocompletion(query, id) {
+       // Replace forbidden characters in regex
+       query = escapeRegex(query);
+       
+       // Create an empty array
+       var results = new Array();
+       
+       // Search in the roster
+       $('#' + id + ' .user').each(function() {
+               var nick = $(this).find('.name').text();
+               var regex = new RegExp('(^)' + query, 'gi');
+               
+               if(nick.match(regex))
+                       results.push(nick);
+       });
+       
+       // Sort the array
+       results = results.sort(caseInsensitiveSort);
+       
+       // Return the results array
+       return results;
+}
+
+// Resets the autocompletion tools
+function resetAutocompletion(hash) {
+       $('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query');
+}
+
+// Autocompletes the chat input nick
+function createAutocompletion(hash) {
+       // Initialize
+       var vSelector = $('#' + hash + ' .message-area');
+       var value = vSelector.val();
+       if(!value)
+               resetAutocompletion(hash);
+       var query = vSelector.attr('data-autocompletion-query');
+       
+       // The autocompletion has not been yet launched
+       if(query == undefined) {
+               query = value;
+               vSelector.attr('data-autocompletion-query', query);
+       }
+       
+       // Get the pointer
+       var pointer = vSelector.attr('data-autocompletion-pointer');
+       var i = 0;
+       
+       if(pointer)
+               i = parseInt(pointer);
+       
+       // We get the nickname
+       var nick = processAutocompletion(query, hash)[i];
+       
+       // Shit, this is my nick!
+       if((nick != undefined) && (nick.toLowerCase() == getMUCNick(hash).toLowerCase())) {
+               // Increment
+               i++;
+               
+               // Get the next nick
+               nick = processAutocompletion(query, hash)[i];
+       }
+       
+       // We quote the nick
+       if(nick != undefined) {
+               // Increment
+               i++;
+               quoteMyNick(hash, nick);
+               
+               // Put a pointer
+               vSelector.attr('data-autocompletion-pointer', i);
+       }
+}
diff --git a/jappixmini/jappix/js/avatar.js b/jappixmini/jappix/js/avatar.js
new file mode 100644 (file)
index 0000000..4234ffc
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+
+Jappix - An open social platform
+These are the avatar JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 01/03/11
+
+*/
+
+// Requests the avatar of a given user
+var AVATAR_PENDING = [];
+
+function getAvatar(xid, mode, enabled, photo) {
+       /* REF: http://xmpp.org/extensions/xep-0153.html */
+       
+       // No need to get the avatar, another process is yet running
+       if(existArrayValue(AVATAR_PENDING, xid))
+               return false;
+       
+       // Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests
+       var xml = XMLFromString(getPersistent('avatar', xid));
+       var forced = false;
+       
+       // Retrieving forced?
+       if($(xml).find('forced').text() == 'true')
+               forced = true;
+       
+       // No avatar in presence
+       if(!photo && !forced && (enabled == 'true')) {
+               // Pending marker
+               AVATAR_PENDING.push(xid);
+               
+               // Reset the avatar
+               resetAvatar(xid, hex_md5(xid));
+               
+               logThis('No avatar for: ' + xid, 2);
+       }
+       
+       // Try to catch the avatar
+       else {
+               // Define some stuffs
+               var type = $(xml).find('type').text();
+               var binval = $(xml).find('binval').text();
+               var checksum = $(xml).find('checksum').text();
+               var updated = false;
+               
+               // Process the checksum of the avatar
+               if((checksum == photo) || (photo == 'forget') || forced)
+                       updated = true;
+               
+               // If the avatar is yet stored and a new retrieving is not needed
+               if((mode == 'cache') && type && binval && checksum && updated) {
+                       // Pending marker
+                       AVATAR_PENDING.push(xid);
+                       
+                       // Display the cache avatar
+                       displayAvatar(xid, hex_md5(xid), type, binval);
+                       
+                       logThis('Read avatar from cache: ' + xid, 3);
+               }
+               
+               // Else if the request has not yet been fired, we get it
+               else if((!updated || (mode == 'cache' && !updated) || (mode == 'force') || (photo = 'forget')) && (enabled != 'false')) {
+                       // Pending marker
+                       AVATAR_PENDING.push(xid);
+                       
+                       // Get the latest avatar
+                       var iq = new JSJaCIQ();
+                       iq.setType('get');
+                       iq.setTo(xid);
+                       
+                       iq.appendNode('vCard', {'xmlns': NS_VCARD});
+                       
+                       con.send(iq, handleAvatar);
+                       
+                       logThis('Get avatar from server: ' + xid, 3);
+               }
+       }
+       
+       return true;
+}
+
+// Handles the avatar
+function handleAvatar(iq) {
+       // Extract the XML values
+       var handleXML = iq.getNode();
+       var handleFrom = fullXID(getStanzaFrom(iq));
+       
+       // Is this me? Remove the resource!
+       if(bareXID(handleFrom) == getXID())
+               handleFrom = bareXID(handleFrom);
+       
+       // Get some other values
+       var hash = hex_md5(handleFrom);
+       var find = $(handleXML).find('vCard');
+       var aChecksum = 'none';
+       var oChecksum = null;
+       
+       // Read our own checksum
+       if(handleFrom == getXID()) {
+               oChecksum = getDB('checksum', 1);
+               
+               // Avoid the "null" value
+               if(!oChecksum)
+                       oChecksum = '';
+       }
+       
+       // vCard not empty?
+       if(find.size()) {
+               // We get our profile details
+               if(handleFrom == getXID()) {
+                       // Get the names
+                       var names = generateBuddyName(iq);
+                       
+                       // Write the values to the database
+                       setDB('profile', 'name', names[0]);
+                       setDB('profile', 'nick', names[1]);
+               }
+               
+               // We get the avatar
+               var aType = find.find('TYPE:first').text();
+               var aBinval = find.find('BINVAL:first').text();
+               
+               // No binval?
+               if(!aBinval) {
+                       aType = 'none';
+                       aBinval = 'none';
+               }
+               
+               // Enough data
+               else {
+                       // No type?
+                       if(!aType)
+                               aType = 'image/png';
+                       
+                       // Process the checksum
+                       else
+                               aChecksum = hex_sha1(Base64.decode(aBinval));
+               }
+               
+               // We display the user avatar
+               displayAvatar(handleFrom, hash, aType, aBinval);
+               
+               // Store the avatar
+               setPersistent('avatar', handleFrom, '<avatar><type>' + aType + '</type><binval>' + aBinval + '</binval><checksum>' + aChecksum + '</checksum><forced>false</forced></avatar>');
+               
+               logThis('Avatar retrieved from server: ' + handleFrom, 3);
+       }
+       
+       // vCard is empty
+       else
+               resetAvatar(handleFrom);
+       
+       // We got a new checksum for us?
+       if(((oChecksum != null) && (oChecksum != aChecksum)) || !FIRST_PRESENCE_SENT) {
+               // Define a proper checksum
+               var pChecksum = aChecksum;
+               
+               if(pChecksum == 'none')
+                       pChecksum = '';
+               
+               // Update our temp. checksum
+               setDB('checksum', 1, pChecksum);
+               
+               // Send the stanza
+               if(FIRST_PRESENCE_SENT)
+                       presenceSend(pChecksum);
+               else
+                       getStorage(NS_OPTIONS);
+       }
+}
+
+// Reset the avatar of an user
+function resetAvatar(xid, hash) {
+       // Store the empty avatar
+       setPersistent('avatar', xid, '<avatar><type>none</type><binval>none</binval><checksum>none</checksum><forced>false</forced></avatar>');
+       
+       // Display the empty avatar
+       displayAvatar(xid, hash, 'none', 'none');
+}
+
+// Displays the avatar of an user
+function displayAvatar(xid, hash, type, binval) {
+       // Initialize the vars
+       var container = hash + ' .avatar-container';
+       var code = '<img class="avatar" src="';
+       
+       // If the avatar exists
+       if((type != 'none') && (binval != 'none'))
+               code += 'data:' + type + ';base64,' + binval;
+       else
+               code += './img/others/default-avatar.png';
+       
+       code += '" alt="" />';
+       
+       // Replace with the new avatar (in the roster and in the chat)
+       $('.' + container).html(code);
+       
+       // We can remove the pending marker
+       removeArrayValue(AVATAR_PENDING, xid);
+}
diff --git a/jappixmini/jappix/js/base64.js b/jappixmini/jappix/js/base64.js
new file mode 100644 (file)
index 0000000..1cf2dc7
--- /dev/null
@@ -0,0 +1,80 @@
+// This code was written by Tyler Akins and has been placed in the
+// public domain.  It would be nice if you left this header intact.
+// Base64 code from Tyler Akins -- http://rumkin.com
+
+var Base64 = (function () {
+    var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+    var obj = {
+        /**
+         * Encodes a string in base64
+         * @param {String} input The string to encode in base64.
+         */
+        encode: function (input) {
+            var output = "";
+            var chr1, chr2, chr3;
+            var enc1, enc2, enc3, enc4;
+            var i = 0;
+        
+            do {
+                chr1 = input.charCodeAt(i++);
+                chr2 = input.charCodeAt(i++);
+                chr3 = input.charCodeAt(i++);
+                
+                enc1 = chr1 >> 2;
+                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+                enc4 = chr3 & 63;
+
+                if (isNaN(chr2)) {
+                    enc3 = enc4 = 64;
+                } else if (isNaN(chr3)) {
+                    enc4 = 64;
+                }
+                
+                output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
+                    keyStr.charAt(enc3) + keyStr.charAt(enc4);
+            } while (i < input.length);
+            
+            return output;
+        },
+        
+        /**
+         * Decodes a base64 string.
+         * @param {String} input The string to decode.
+         */
+        decode: function (input) {
+            var output = "";
+            var chr1, chr2, chr3;
+            var enc1, enc2, enc3, enc4;
+            var i = 0;
+            
+            // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+            
+            do {
+                enc1 = keyStr.indexOf(input.charAt(i++));
+                enc2 = keyStr.indexOf(input.charAt(i++));
+                enc3 = keyStr.indexOf(input.charAt(i++));
+                enc4 = keyStr.indexOf(input.charAt(i++));
+                
+                chr1 = (enc1 << 2) | (enc2 >> 4);
+                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+                chr3 = ((enc3 & 3) << 6) | enc4;
+                
+                output = output + String.fromCharCode(chr1);
+                
+                if (enc3 != 64) {
+                    output = output + String.fromCharCode(chr2);
+                }
+                if (enc4 != 64) {
+                    output = output + String.fromCharCode(chr3);
+                }
+            } while (i < input.length);
+            
+            return output;
+        }
+    };
+
+    return obj;
+})();
diff --git a/jappixmini/jappix/js/board.js b/jappixmini/jappix/js/board.js
new file mode 100644 (file)
index 0000000..1d26ace
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+
+Jappix - An open social platform
+These are the notification board JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 12/03/11
+
+*/
+
+// Creates a board panel
+function createBoard(type, id) {
+       // Text var
+       var text = '';
+       
+       // Info
+       if(type == 'info') {
+               switch(id) {
+                       // Password change
+                       case 1:
+                               text = _e("Your password has been changed, now you can connect to your account with your new login data.");
+                               
+                               break;
+                       
+                       // Account deletion
+                       case 2:
+                               text = _e("Your XMPP account has been removed, bye!");
+                               
+                               break;
+                       
+                       // Account logout
+                       case 3:
+                               text = _e("You have been logged out of your XMPP account, have a nice day!");
+                               
+                               break;
+                       
+                       // Groupchat join
+                       case 4:
+                               text = _e("The room you joined seems not to exist. You should create it!");
+                               
+                               break;
+                       
+                       // Groupchat removal
+                       case 5:
+                               text = _e("The groupchat has been removed, now someone else will be able to recreate it.");
+                               
+                               break;
+                       
+                       // Non-existant groupchat user
+                       case 6:
+                               text = _e("The user that you want to reach is not present in the room.");
+                               
+                               break;
+               }
+       }
+       
+       // Error
+       else {
+               switch(id) {
+                       // Custom error
+                       case 1:
+                               text = '<b>' + _e("Error") + '</b> &raquo; <span></span>';
+                               
+                               break;
+                       
+                       // Network error
+                       case 2:
+                               text = _e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
+                               
+                               break;
+                       
+                       // List retrieving error
+                       case 3:
+                               text = _e("The element list on this server could not be obtained!");
+                               
+                               break;
+                       
+                       // Attaching error
+                       case 4:
+                               text = printf(_e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
+                               
+                               break;
+               }
+       }
+       
+       // No text?
+       if(!text)
+               return false;
+       
+       // Append the content
+       $('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>');
+       
+       // Events (click and auto-hide)
+       $('#board .one-board.' + type + '[data-id=' + id + ']')
+       
+       .click(function() {
+               closeThisBoard(this);
+       })
+       
+       .oneTime('5s', function() {
+               closeThisBoard(this);
+       })
+       
+       .slideDown();
+       
+       return true;
+}
+
+// Destroys the existing board notifications
+function destroyBoard() {
+       $('#board').empty();
+}
+
+// Executes a given action on the notification board
+function actionBoard(id, type) {
+       // In a first, we destroy other boards
+       destroyBoard();
+       
+       // Then we display the board
+       createBoard(type, id);
+}
+
+// Opens a given error ID
+function openThisError(id) {
+       actionBoard(id, 'error');
+}
+
+// Opens a given info ID
+function openThisInfo(id) {
+       actionBoard(id, 'info');
+}
+
+// Closes a given board
+function closeThisBoard(board) {
+       $(board).slideUp('normal', function() {
+               $(this).remove();
+       });
+}
diff --git a/jappixmini/jappix/js/browser-detect.js b/jappixmini/jappix/js/browser-detect.js
new file mode 100644 (file)
index 0000000..39edaf2
--- /dev/null
@@ -0,0 +1,124 @@
+/* BROWSER DETECT
+ * http://www.quirksmode.org/js/detect.html
+ */
+
+var BrowserDetect = {
+       init: function () {
+               this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
+               this.version = this.searchVersion(navigator.userAgent)
+                       || this.searchVersion(navigator.appVersion)
+                       || "an unknown version";
+               this.OS = this.searchString(this.dataOS) || "an unknown OS";
+       },
+       
+       searchString: function (data) {
+               for (var i=0;i<data.length;i++) {
+                       var dataString = data[i].string;
+                       var dataProp = data[i].prop;
+                       this.versionSearchString = data[i].versionSearch || data[i].identity;
+                       if (dataString) {
+                               if (dataString.indexOf(data[i].subString) != -1)
+                                       return data[i].identity;
+                       }
+                       else if (dataProp)
+                               return data[i].identity;
+               }
+       },
+       
+       searchVersion: function (dataString) {
+               var index = dataString.indexOf(this.versionSearchString);
+               if (index == -1) return;
+               return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
+       },
+       
+       dataBrowser: [
+               {
+                       string: navigator.userAgent,
+                       subString: "Chrome",
+                       identity: "Chrome"
+               },
+               {       string: navigator.userAgent,
+                       subString: "OmniWeb",
+                       versionSearch: "OmniWeb/",
+                       identity: "OmniWeb"
+               },
+               {
+                       string: navigator.vendor,
+                       subString: "Apple",
+                       identity: "Safari",
+                       versionSearch: "Version"
+               },
+               {
+                       prop: window.opera,
+                       identity: "Opera"
+               },
+               {
+                       string: navigator.vendor,
+                       subString: "iCab",
+                       identity: "iCab"
+               },
+               {
+                       string: navigator.vendor,
+                       subString: "KDE",
+                       identity: "Konqueror"
+               },
+               {
+                       string: navigator.userAgent,
+                       subString: "Firefox",
+                       identity: "Firefox"
+               },
+               {
+                       string: navigator.vendor,
+                       subString: "Camino",
+                       identity: "Camino"
+               },
+               {               // for newer Netscapes (6+)
+                       string: navigator.userAgent,
+                       subString: "Netscape",
+                       identity: "Netscape"
+               },
+               {
+                       string: navigator.userAgent,
+                       subString: "MSIE",
+                       identity: "Explorer",
+                       versionSearch: "MSIE"
+               },
+               {
+                       string: navigator.userAgent,
+                       subString: "Gecko",
+                       identity: "Mozilla",
+                       versionSearch: "rv"
+               },
+               {               // for older Netscapes (4-)
+                       string: navigator.userAgent,
+                       subString: "Mozilla",
+                       identity: "Netscape",
+                       versionSearch: "Mozilla"
+               }
+       ],
+       
+       dataOS : [
+               {
+                       string: navigator.platform,
+                       subString: "Win",
+                       identity: "Windows"
+               },
+               {
+                       string: navigator.platform,
+                       subString: "Mac",
+                       identity: "Mac"
+               },
+               {
+                          string: navigator.userAgent,
+                          subString: "iPhone",
+                          identity: "iPhone/iPod"
+           },
+               {
+                       string: navigator.platform,
+                       subString: "Linux",
+                       identity: "Linux"
+               }
+       ]
+};
+
+BrowserDetect.init();
diff --git a/jappixmini/jappix/js/bubble.js b/jappixmini/jappix/js/bubble.js
new file mode 100644 (file)
index 0000000..9006f64
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+
+Jappix - An open social platform
+These are the bubble JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 11/12/10
+
+*/
+
+// Closes all the opened bubbles
+function closeBubbles() {
+       // Destroy all the elements
+       $('.bubble.hidable:visible').hide();
+       $('.bubble.removable').remove();
+       $('body').die('click');
+       
+       return false;
+}
+
+// Click function when a bubble is opened
+function showBubble(selector) {
+       // Hidable bubbles special things
+       if($(selector).is('.hidable')) {
+               // This bubble is yet displayed? So abort!
+               if($(selector).is(':visible'))
+                       return closeBubbles();
+               
+               // Close all the bubbles
+               closeBubbles();
+               
+               // Show the requested bubble
+               $(selector).show();
+       }
+       
+       // Removable bubbles special things
+       else {
+               // This bubble is yet added? So abort!
+               if(exists(selector))
+                       return closeBubbles();
+               
+               // Close all the bubbles
+               closeBubbles();
+       }
+       
+       // Creates a new click event to close the bubble
+       $('body').live('click', function(evt) {
+               var target = evt.target;
+               
+               // If this is a click away from a bubble
+               if(!$(target).parents('.ibubble').size())
+                       closeBubbles();
+       });
+       
+       return false;
+}
diff --git a/jappixmini/jappix/js/caps.js b/jappixmini/jappix/js/caps.js
new file mode 100644 (file)
index 0000000..d33949c
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+
+Jappix - An open social platform
+These are the CAPS JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Returns an array of the Jappix disco#infos
+function myDiscoInfos() {
+       var fArray = new Array(
+               NS_MUC,
+               NS_MUC_USER,
+               NS_MUC_ADMIN,
+               NS_MUC_OWNER,
+               NS_MUC_CONFIG,
+               NS_DISCO_INFO,
+               NS_DISCO_ITEMS,
+               NS_PUBSUB_RI,
+               NS_BOSH,
+               NS_CAPS,
+               NS_MOOD,
+               NS_ACTIVITY,
+               NS_TUNE,
+               NS_GEOLOC,
+               NS_NICK,
+               NS_URN_ADATA,
+               NS_URN_AMETA,
+               NS_URN_MBLOG,
+               NS_URN_INBOX,
+               NS_MOOD + NS_NOTIFY,
+               NS_ACTIVITY + NS_NOTIFY,
+               NS_TUNE + NS_NOTIFY,
+               NS_GEOLOC + NS_NOTIFY,
+               NS_URN_MBLOG + NS_NOTIFY,
+               NS_URN_INBOX + NS_NOTIFY,
+               NS_URN_DELAY,
+               NS_ROSTER,
+               NS_ROSTERX,
+               NS_HTTP_AUTH,
+               NS_CHATSTATES,
+               NS_XHTML_IM,
+               NS_IPV6,
+               NS_LAST,
+               NS_PRIVATE,
+               NS_REGISTER,
+               NS_SEARCH,
+               NS_COMMANDS,
+               NS_VERSION,
+               NS_XDATA,
+               NS_VCARD,
+               NS_URN_TIME,
+               NS_URN_PING,
+               NS_URN_ARCHIVE,
+               NS_URN_AR_PREF,
+               NS_URN_RECEIPTS,
+               NS_PRIVACY,
+               NS_IQOOB,
+               NS_XOOB
+       );
+       
+       return fArray;
+}
+
+// Gets the disco#infos of an entity
+function getDiscoInfos(to, caps) {
+       // No CAPS
+       if(!caps) {
+               logThis('No CAPS: ' + to, 2);
+               
+               displayDiscoInfos(to, '');
+               
+               return false;
+       }
+       
+       // Get the stored disco infos
+       var xml = XMLFromString(getPersistent('caps', caps));
+       
+       // Yet stored
+       if(xml) {
+               logThis('CAPS from cache: ' + to, 3);
+               
+               displayDiscoInfos(to, xml);
+               
+               return true;
+       }
+       
+       logThis('CAPS from the network: ' + to, 3);
+       
+       // Not stored: get the disco#infos
+       var iq = new JSJaCIQ();
+       
+       iq.setTo(to);
+       iq.setType('get');
+       iq.setQuery(NS_DISCO_INFO);
+       
+       con.send(iq, handleDiscoInfos);
+       
+       return true;
+}
+
+// Handles the disco#infos of an entity
+function handleDiscoInfos(iq) {
+       if(!iq || (iq.getType() == 'error'))
+               return;
+       
+       // IQ received, get some values
+       var from = fullXID(getStanzaFrom(iq));
+       var query = iq.getQuery();
+       
+       // Generate the CAPS-processing values
+       var identities = new Array();
+       var features = new Array();
+       var data_forms = new Array();
+       
+       // Identity values
+       $(query).find('identity').each(function() {
+               var pCategory = $(this).attr('category');
+               var pType = $(this).attr('type');
+               var pLang = $(this).attr('xml:lang');
+               var pName = $(this).attr('name');
+               
+               if(!pCategory)
+                       pCategory = '';
+               if(!pType)
+                       pType = '';
+               if(!pLang)
+                       pLang = '';
+               if(!pName)
+                       pName = '';
+               
+               identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
+       });
+       
+       // Feature values
+       $(query).find('feature').each(function() {
+               var pVar = $(this).attr('var');
+               
+               // Add the current value to the array
+               if(pVar)
+                       features.push(pVar);
+       });
+       
+       // Data-form values
+       $(query).find('x[xmlns=' + NS_XDATA + ']').each(function() {
+               // Initialize some stuffs
+               var pString = '';
+               var sortVar = new Array();
+               
+               // Add the form type field
+               $(this).find('field[var=FORM_TYPE] value').each(function() {
+                       var cText = $(this).text();
+                       
+                       if(cText)
+                               pString += cText + '<';
+               });
+               
+               // Add the var attributes into an array
+               $(this).find('field:not([var=FORM_TYPE])').each(function() {
+                       var cVar = $(this).attr('var');
+                       
+                       if(cVar)
+                               sortVar.push(cVar);
+               });
+               
+               // Sort the var attributes
+               sortVar = sortVar.sort();
+               
+               // Loop this sorted var attributes
+               for(i in sortVar) {
+                       // Initialize the value sorting
+                       var sortVal = new Array();
+                       
+                       // Append it to the string
+                       pString += sortVar[i] + '<';
+                       
+                       // Add each value to the array
+                       $(this).find('field[var=' + sortVar[i] + '] value').each(function() {
+                               sortVal.push($(this).text());
+                       });
+                       
+                       // Sort the values
+                       sortVal = sortVal.sort();
+                       
+                       // Append the values to the string
+                       for(j in sortVal)
+                               pString += sortVal[j] + '<';
+               }
+               
+               // Any string?
+               if(pString) {
+                       // Remove the undesired double '<' from the string
+                       if(pString.match(/(.+)(<)+$/))
+                               pString = pString.substring(0, pString.length - 1);
+                       
+                       // Add the current string to the array
+                       data_forms.push(pString);
+               }
+       });
+       
+       // Process the CAPS
+       var caps = processCaps(identities, features, data_forms);
+       
+       // Get the XML string
+       var xml = xmlToString(query);
+       
+       // Store the disco infos
+       setPersistent('caps', caps, xml);
+       
+       // This is our server
+       if(from == getServer()) {
+               // Handle the features
+               handleFeatures(xml);
+               
+               logThis('Got our server CAPS', 3);
+       }
+       
+       else {
+               // Display the disco infos
+               displayDiscoInfos(from, xml);
+               
+               logThis('Got CAPS: ' + from, 3);
+       }
+}
+
+// Displays the disco#infos everywhere needed for an entity
+function displayDiscoInfos(from, xml) {
+       // Generate the chat path
+       var xid = bareXID(from);
+       
+       // This comes from a private groupchat chat?
+       if(isPrivate(xid))
+               xid = from;
+       
+       hash = hex_md5(xid);
+       
+       // Support indicators
+       var xhtml_im = false;
+       var iq_oob = false;
+       var x_oob = false;
+       var receipts = false;
+       
+       // Display the supported features
+       $(xml).find('feature').each(function() {
+               var current = $(this).attr('var');
+               
+               // xHTML-IM
+               if(current == NS_XHTML_IM)
+                       xhtml_im = true;
+               
+               // Out of Band Data (IQ)
+               if(current == NS_IQOOB)
+                       iq_oob = true;
+               
+               // Out of Band Data (X)
+               if(current == NS_XOOB)
+                       x_oob = true;
+               
+               // Receipts
+               else if(current == NS_URN_RECEIPTS)
+                       receipts = true;
+       });
+       
+       // Paths
+       var path = $('#' + hash);
+       var message_area = path.find('.message-area');
+       var style = path.find('.chat-tools-style');
+       var file = path.find('.chat-tools-file');
+       
+       // Apply xHTML-IM
+       if(xhtml_im)
+               style.show();
+       else {
+               // Remove the tooltip elements
+               style.hide();
+               style.find('.bubble-style').remove();
+               
+               // Reset the markers
+               message_area.removeAttr('style')
+                           .removeAttr('data-color')
+                           .removeAttr('data-bold')
+                           .removeAttr('data-italic')
+                           .removeAttr('data-underline');
+       }
+       
+       // Apply Out of Band Data
+       if(iq_oob || x_oob) {
+               file.show();
+               
+               // Set a marker
+               if(iq_oob)
+                       file.attr('data-oob', 'iq');
+               else
+                       file.attr('data-oob', 'x');
+       }
+       
+       else {
+               // Remove the tooltip elements
+               file.hide();
+               file.find('.bubble-style').remove();
+               
+               // Reset the marker
+               file.removeAttr('data-oob');
+       }
+       
+       // Apply receipts
+       if(receipts)
+               message_area.attr('data-receipts', 'true');
+       else
+               message_area.removeAttr('data-receipts');
+}
+
+// Generates the CAPS hash
+function processCaps(cIdentities, cFeatures, cDataForms) {
+       // Initialize
+       var cString = '';
+       
+       // Sort the arrays
+       cIdentities = cIdentities.sort();
+       cFeatures = cFeatures.sort();
+       cDataForms = cDataForms.sort();
+       
+       // Process the sorted identity string
+       for(a in cIdentities)
+               cString += cIdentities[a] + '<';
+       
+       // Process the sorted feature string
+       for(b in cFeatures)
+               cString += cFeatures[b] + '<';
+       
+       // Process the sorted data-form string
+       for(c in cDataForms)
+               cString += cDataForms[c] + '<';
+       
+       // Process the SHA-1 hash
+       var cHash = b64_sha1(cString);
+       
+       return cHash;
+}
+
+// Generates the Jappix CAPS hash
+function myCaps() {
+       return processCaps(new Array('client/web//Jappix'), myDiscoInfos(), new Array());
+}
diff --git a/jappixmini/jappix/js/chat.js b/jappixmini/jappix/js/chat.js
new file mode 100644 (file)
index 0000000..c67bfac
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+
+Jappix - An open social platform
+These are the chat JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Eric
+Last revision: 16/10/11
+
+*/
+
+// Correctly opens a new chat
+function checkChatCreate(xid, type, nickname, password, title) {
+       // No XID?
+       if(!xid)
+               return false;
+       
+       // We generate some stuffs
+       var hash = hex_md5(xid);
+       var name;
+       
+       // Gets the name of the user/title of the room
+       if(title)
+               name = title;
+       
+       else {
+               // Private groupchat chat
+               if(type == 'private')
+                       name = thisResource(xid);
+               
+               // XMPP-ID
+               else if(xid.indexOf('@') != -1)
+                       name = getBuddyName(xid);
+               
+               // Gateway
+               else
+                       name = xid;
+       }
+       
+       // If the target div does not exist
+       if(!exists('#' + hash)) {
+               // We check the type of the chat to open
+               if((type == 'chat') || (type == 'private'))
+                       chatCreate(hash, xid, name, type);
+               
+               else if(type == 'groupchat') {
+                       // Try to read the room stored configuration
+                       if(!isAnonymous() && (!nickname || !password || !title)) {
+                               // Catch the room data
+                               var fData = $(XMLFromString(getDB('favorites', xid)));
+                               var fNick = fData.find('nick').text();
+                               var fPwd = fData.find('password').text();
+                               var fName = fData.find('name').text();
+                               
+                               // Apply the room data
+                               if(!nickname && fNick)
+                                       nickname = fNick;
+                               if(!password && fPwd)
+                                       password = fPwd;
+                               if(!title && fName)
+                                       name = fName;
+                       }
+                       
+                       groupchatCreate(hash, xid, name, nickname, password);
+               }
+       }
+       
+       // Switch to the newly-created chat
+       switchChan(hash);
+       
+       return false;
+}
+
+// Generates the chat DOM elements
+function generateChat(type, id, xid, nick) {
+       // Generate some stuffs
+       var path = '#' + id + ' .';
+       var escaped_xid = escape(xid);
+       
+       // Special code
+       var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle;
+       
+       // Groupchat special code
+       if(type == 'groupchat') {
+               specialAttributes = ' data-type="groupchat"';
+               specialAvatar = '';
+               specialName = '<p class="bc-infos"><b>' + _e("Subject") + '</b> <span class="muc-topic">' + _e("no subject defined for this room.") + '</span></p>';
+               specialCode = '<div class="content groupchat-content" id="chat-content-' + id + '"></div><div class="list"><div class="moderator role"><p class="title">' + _e("Moderators") + '</p></div><div class="participant role"><p class="title">' + _e("Participants") + '</p></div><div class="visitor role"><p class="title">' + _e("Visitors") + '</p></div><div class="none role"><p class="title">' + _e("Others") + '</p></div></div>';
+               specialLink = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + _e("Administration panel for this room") + '"></a>';
+               specialStyle = '';
+               
+               // Is this a gateway?
+               if(xid.match(/%/))
+                       specialDisabled = '';
+               else
+                       specialDisabled = ' disabled=""';
+       }
+       
+       // Chat (or other things?!) special code
+       else {
+               specialAttributes = ' data-type="chat"';
+               specialAvatar = '<div class="avatar-container"><img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" /></div>';
+               specialName = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
+               specialCode = '<div class="content" id="chat-content-' + id + '"></div>';
+               specialLink = '<a href="#" class="tools-archives tools-tooltip talk-images chat-tools-content" title="' + _e("View chat history") + '"></a><a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + _e("Show user profile") + '"></a>';
+               specialStyle = ' style="display: none;"';
+               specialDisabled = '';
+       }
+       
+       // Not a groupchat private chat, we can use the buddy add icon
+       if((type == 'chat') || (type == 'groupchat')) {
+               var addTitle;
+               
+               if(type == 'chat')
+                       addTitle = _e("Add this contact to your friends");
+               else
+                       addTitle = _e("Add this groupchat to your favorites");
+               
+               specialLink += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + addTitle + '"></a>';
+       }
+       
+       // IE DOM parsing bug fix
+       var specialStylePicker = '<div class="chat-tools-content chat-tools-style"' + specialStyle + '>' + 
+                                       '<a href="#" class="tools-style tools-tooltip talk-images"></a>' + 
+                                '</div>';
+       
+       if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
+               specialStylePicker = '';
+       
+       // Append the chat HTML code
+       $('#page-engine').append(
+               '<div id="' + id + '" class="page-engine-chan chat one-counter"' + specialAttributes + ' data-xid="' + escaped_xid + '">' + 
+                       '<div class="top ' + id + '">' + 
+                               specialAvatar + 
+                               
+                               '<div class="name">' + 
+                                       '<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' + 
+                                       specialName + 
+                               '</div>' + 
+                       '</div>' + 
+                       
+                       specialCode + 
+                       
+                       '<div class="text">' + 
+                               '<div class="footer">' + 
+                                       '<div class="chat-tools-content chat-tools-smileys">' + 
+                                               '<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' + 
+                                       '</div>' + 
+                                       
+                                       specialStylePicker + 
+                                       
+                                       '<div class="chat-tools-content chat-tools-file">' + 
+                                               '<a href="#" class="tools-file tools-tooltip talk-images"></a>' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="chat-tools-content chat-tools-save">' + 
+                                               '<a href="#" class="tools-save tools-tooltip talk-images"></a>' + 
+                                       '</div>' + 
+                                       
+                                       '<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + _e("Clean current chat") + '"></a>' + 
+                                       
+                                       specialLink + 
+                               '</div>' + 
+                               
+                               '<div class="compose">' + 
+                                       '<textarea class="message-area focusable" ' + specialDisabled + ' data-to="' + escaped_xid + '" /></textarea>' + 
+                               '</div>' + 
+                       '</div>' + 
+               '</div>'
+       );
+       
+       // Click event: chat cleaner
+       $(path + 'tools-clear').click(function() {
+               cleanChat(id);
+       });
+       
+       // Click event: user-infos
+       $(path + 'tools-infos').click(function() {
+               openUserInfos(xid);
+       });
+}
+
+// Generates the chat switch elements
+function generateSwitch(type, id, xid, nick) {
+       // Path to the element
+       var chat_switch = '#page-switch .';
+       
+       // Special code
+       var specialClass = ' unavailable';
+       var show_close = true;
+       
+       // Groupchat
+       if(type == 'groupchat') {
+               specialClass = ' groupchat-default';
+               
+               if(isAnonymous() && (xid == generateXID(ANONYMOUS_ROOM, 'groupchat')))
+                       show_close = false;
+       }
+       
+       // Generate the HTML code
+       var html = '<div class="' + id + ' switcher chan" onclick="return switchChan(\'' + encodeOnclick(id) + '\')">' + 
+                       '<div class="icon talk-images' + specialClass + '"></div>' + 
+                       
+                       '<div class="name">' + nick.htmlEnc() + '</div>';
+       
+       // Show the close button if not MUC and not anonymous
+       if(show_close)
+               html += '<div class="exit" title="' + _e("Close this tab") + '" onclick="return quitThisChat(\'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(type) + '\');">x</div>';
+       
+       // Close the HTML
+       html += '</div>';
+       
+       // Append the HTML code
+       $(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html);
+}
+
+// Cleans given the chat lines
+function cleanChat(chat) {
+       $('#page-engine #' + chat + ' .content .one-group').remove();
+       
+       $(document).oneTime(10, function() {
+               $('#page-engine #' + chat + ' .text .message-area').focus();
+       });
+}
+
+// Creates a new chat
+function chatCreate(hash, xid, nick, type) {
+       logThis('New chat: ' + xid, 3);
+       
+       // Create the chat content
+       generateChat(type, hash, xid, nick);
+       
+       // Create the chat switcher
+       generateSwitch(type, hash, xid, nick);
+       
+       // If the user is not in our buddy-list
+       if(type == 'chat') {
+               // Add button
+               if(!exists('#buddy-list .buddy[data-xid=' + escape(xid) + ']'))
+                       $('#' + hash + ' .tools-add').click(function() {
+                               // Hide the icon (to tell the user all is okay)
+                               $(this).hide();
+                               
+                               // Send the subscribe request
+                               addThisContact(xid, nick);
+                       }).show();
+               
+               // Archives button
+               else if(enabledArchives() || enabledArchives('auto') || enabledArchives('manual') || enabledArchives('manage'))
+                       $('#' + hash + ' .tools-archives').click(function() {
+                               // Open the archives popup
+                               openArchives();
+                               
+                               // Get the archives for this user
+                               $('#archives .filter .friend').val(xid);
+                               updateArchives();
+                       }).show();
+       }
+       
+       // We catch the user's informations (like this avatar, vcard, and so on...)
+       getUserInfos(hash, xid, nick, type);
+       
+       // The icons-hover functions
+       tooltipIcons(xid, hash);
+       
+       // The event handlers
+       var inputDetect = $('#page-engine #' + hash + ' .message-area');
+       
+       inputDetect.focus(function() {
+               chanCleanNotify(hash);
+       })
+       
+       inputDetect.keypress(function(e) {
+               // Enter key
+               if(e.keyCode == 13) {
+                       // Add a new line
+                       if(e.shiftKey)
+                               inputDetect.val(inputDetect.val() + '\n');
+                       
+                       // Send the message
+                       else {
+                               // Send the message
+                               sendMessage(hash, 'chat');
+                               
+                               // Reset the composing database entry
+                               setDB('chatstate', xid, 'off');
+                       }
+                       
+                       return false;
+               }
+       });
+       
+       // Chatstate events
+       eventsChatState(inputDetect, xid, hash);
+}
diff --git a/jappixmini/jappix/js/chatstate.js b/jappixmini/jappix/js/chatstate.js
new file mode 100644 (file)
index 0000000..de7e796
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+
+Jappix - An open social platform
+These are the chatstate JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 25/08/11
+
+*/
+
+// Sends a given chatstate to a given entity
+function chatStateSend(state, xid, hash) {
+       var user_type = $('#' + hash).attr('data-type');
+       
+       // If the friend client supports chatstates and is online
+       if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !exists('#page-switch .' + hash + ' .unavailable'))) {
+               // Already sent?
+               if(getDB('currentchatstate', xid) == state)
+                       return;
+               
+               // Write the state
+               setDB('currentchatstate', xid, state);
+               
+               // New message stanza
+               var aMsg = new JSJaCMessage();
+               aMsg.setTo(xid);
+               aMsg.setType(user_type);
+               
+               // Append the chatstate node
+               aMsg.appendNode(state, {'xmlns': NS_CHATSTATES});
+               
+               // Send this!
+               con.send(aMsg);
+       }
+}
+
+// Displays a given chatstate in a given chat
+function displayChatState(state, hash, type) {
+       // Groupchat?
+       if(type == 'groupchat') {
+               resetChatState(hash, type);
+               
+               // "gone" state not allowed
+               if(state != 'gone')
+                       $('#page-engine .page-engine-chan .user.' + hash).addClass(state);
+       }
+       
+       // Chat
+       else {
+               // We change the buddy name color in the page-switch
+               resetChatState(hash, type);
+               $('#page-switch .' + hash + ' .name').addClass(state);
+               
+               // We generate the chatstate text
+               var text = '';
+               
+               switch(state) {
+                       // Active
+                       case 'active':
+                               text = _e("Your friend is paying attention to the conversation.");
+                               
+                               break;
+                       
+                       // Composing
+                       case 'composing':
+                               text = _e("Your friend is writing a message...");
+                               
+                               break;
+                       
+                       // Paused
+                       case 'paused':
+                               text = _e("Your friend stopped writing a message.");
+                               
+                               break;
+                       
+                       // Inactive
+                       case 'inactive':
+                               text = _e("Your friend is doing something else.");
+                               
+                               break;
+                       
+                       // Gone
+                       case 'gone':
+                               text = _e("Your friend closed the chat.");
+                               
+                               break;
+               }
+               
+               // We reset the previous state
+               $('#' + hash + ' .chatstate').remove();
+               
+               // We create the chatstate
+               $('#' + hash + ' .content').after('<div class="' + state + ' chatstate">' + text + '</div>');
+       }
+}
+
+// Resets the chatstate switcher marker
+function resetChatState(hash, type) {
+       // Define the selector
+       var selector;
+       
+       if(type == 'groupchat')
+               selector = $('#page-engine .page-engine-chan .user.' + hash);
+       else
+               selector = $('#page-switch .' + hash + ' .name');
+       
+       // Reset!
+       selector.removeClass('active')
+       selector.removeClass('composing')
+       selector.removeClass('paused')
+       selector.removeClass('inactive')
+       selector.removeClass('gone');
+}
+
+// Adds the chatstate events
+function eventsChatState(target, xid, hash) {
+       target.keyup(function(e) {
+               if(e.keyCode != 13) {
+                       // Composing a message
+                       if($(this).val() && (getDB('chatstate', xid) != 'on')) {
+                               // We change the state detect input
+                               setDB('chatstate', xid, 'on');
+                               
+                               // We send the friend a "composing" chatstate
+                               chatStateSend('composing', xid, hash);
+                       }
+                       
+                       // Stopped composing a message
+                       else if(!$(this).val() && (getDB('chatstate', xid) == 'on')) {
+                               // We change the state detect input
+                               setDB('chatstate', xid, 'off');
+                               
+                               // We send the friend an "active" chatstate
+                               chatStateSend('active', xid, hash);
+                       }
+               }
+       });
+       
+       target.change(function() {
+               // Reset the composing database entry
+               setDB('chatstate', xid, 'off');
+       });
+       
+       target.focus(function() {
+               // Not needed
+               if(target.is(':disabled'))
+                       return;
+               
+               // Nothing in the input, user is active
+               if(!$(this).val())
+                       chatStateSend('active', xid, hash);
+               
+               // Something was written, user started writing again
+               else
+                       chatStateSend('composing', xid, hash);
+       });
+       
+       target.blur(function() {
+               // Not needed
+               if(target.is(':disabled'))
+                       return;
+               
+               // Nothing in the input, user is inactive
+               if(!$(this).val())
+                       chatStateSend('inactive', xid, hash);
+               
+               // Something was written, user paused
+               else
+                       chatStateSend('paused', xid, hash);
+       });
+}
diff --git a/jappixmini/jappix/js/common.js b/jappixmini/jappix/js/common.js
new file mode 100644 (file)
index 0000000..ab10d6e
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+
+Jappix - An open social platform
+These are the common JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, olivierm
+Last revision: 24/06/11
+
+*/
+
+// Checks if an element exists in the DOM
+function exists(selector) {
+       if(jQuery(selector).size() > 0)
+               return true;
+       else
+               return false;
+}
+
+// Checks if Jappix is connected
+function isConnected() {
+       if((typeof con != 'undefined') && con && con.connected())
+               return true;
+       
+       return false;
+}
+
+// Checks if Jappix has focus
+function isFocused() {
+       try {
+               if(document.hasFocus())
+                       return true;
+               
+               return false;
+       }
+       
+       catch(e) {
+               return true;
+       }
+}
+
+// Generates the good XID
+function generateXID(xid, type) {
+       // XID needs to be transformed
+       if(xid && (xid.indexOf('@') == -1)) {
+               // Groupchat
+               if(type == 'groupchat')
+                       return xid + '@' + HOST_MUC;
+               
+               // One-to-one chat
+               if(xid.indexOf('.') == -1)
+                       return xid + '@' + HOST_MAIN;
+               
+               // It might be a gateway?
+               return xid;
+       }
+       
+       // Nothing special (yet bare XID)
+       return xid;
+}
+
+// Gets the asked translated string
+function _e(string) {
+       return string;
+}
+
+// Replaces '%s' to a given value for a translated string
+function printf(string, value) {
+       return string.replace('%s', value);
+}
+
+// Properly explodes a string with a given character
+function explodeThis(toEx, toStr, i) {
+       // Get the index of our char to explode
+       var index = toStr.indexOf(toEx);
+       
+       // We split if necessary the string
+       if(index != -1) {
+               if(i == 0)
+                       toStr = toStr.substr(0, index);
+               else
+                       toStr = toStr.substr(index + 1);
+       }
+       
+       // We return the value
+       return toStr;
+}
+
+// Cuts the resource of a XID
+function cutResource(aXID) {
+       return explodeThis('/', aXID, 0);
+}
+
+// Gets the resource of a XID
+function thisResource(aXID) {
+       // Any resource?
+       if(aXID.indexOf('/') != -1)
+               return explodeThis('/', aXID, 1);
+       
+       // No resource
+       return '';
+}
+
+// Does stringprep on a string
+function stringPrep(string) {
+       // Replacement arrays
+       var invalid = new Array('Š', 'š', 'Đ', 'đ', 'Ž', 'ž', 'Č', 'č', 'Ć', 'ć', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ý', 'þ', 'ÿ', 'Ŕ', 'ŕ');
+       
+       var valid   = new Array('S', 's', 'Dj', 'dj', 'Z', 'z', 'C', 'c', 'C', 'c', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 'B', 'Ss', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'o', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'y', 'b', 'y', 'R', 'r');
+       
+       // Compute a new string
+       for(i in invalid)
+               string = string.replace(invalid[i], valid[i]);
+       
+       return string;
+}
+
+// Encodes quotes in a string
+function encodeQuotes(str) {
+       return (str + '').replace(/"/g, '&quot;');
+}
+
+// Gets the bare XID from a XID
+function bareXID(xid) {
+       // Cut the resource
+       xid = cutResource(xid);
+       
+       // Launch the stringprep
+       xid = stringPrep(xid);
+       
+       // Set the XID to lower case
+       xid = xid.toLowerCase();
+       
+       return xid;
+}
+
+// Gets the full XID from a XID
+function fullXID(xid) {
+       // Normalizes the XID
+       var full = bareXID(xid);
+       var resource = thisResource(xid);
+       
+       // Any resource?
+       if(resource)
+               full += '/' + resource;
+       
+       return full;
+}
+
+// Gets the nick from a XID
+function getXIDNick(aXID) {
+       return explodeThis('@', aXID, 0);
+}
+
+// Gets the host from a XID
+function getXIDHost(aXID) {
+       return explodeThis('@', aXID, 1);
+}
+
+// Checks if we are in developer mode
+function isDeveloper() {
+       if(DEVELOPER == 'on')
+               return true;
+       
+       return false;
+}
+
+// Checks if anonymous mode is allowed
+function allowedAnonymous() {
+       if(ANONYMOUS == 'on')
+               return true;
+       
+       return false;
+}
+
+// Checks if host is locked
+function lockHost() {
+       if(LOCK_HOST == 'on')
+               return true;
+       
+       return false;
+}
+
+// Gets the full XID of the user
+function getXID() {
+       // Return the XID of the user
+       if(con.username && con.domain)
+               return con.username + '@' + con.domain;
+       
+       return '';
+}
+
+// Generates the colors for a given user XID
+function generateColor(xid) {
+       var colors = new Array(
+                       'ac0000',
+                       'a66200',
+                       '007703',
+                       '00705f',
+                       '00236b',
+                       '4e005c'
+                    );
+       
+       var number = 0;
+       
+       for(var i = 0; i < xid.length; i++)
+               number += xid.charCodeAt(i);
+       
+       var color = '#' + colors[number % (colors.length)];
+       
+       return color;
+}
+
+// Checks if the XID is a gateway
+function isGateway(xid) {
+       if(xid.indexOf('@') != -1)
+               return false;
+       
+       return true;
+}
+
+// Gets the from attribute of a stanza (overrides some servers like Prosody missing from attributes)
+function getStanzaFrom(stanza) {
+       var from = stanza.getFrom();
+       
+       // No from, we assume this is our XID
+       if(!from)
+               from = getXID();
+       
+       return from;
+}
+
+// Logs a given data in the console
+function logThis(data, level) {
+       // Console not available
+       if(!isDeveloper() || (typeof(console) == 'undefined'))
+               return false;
+       
+       // Switch the log level
+       switch(level) {
+               // Debug
+               case 0:
+                       console.debug(data);
+                       
+                       break;
+               
+               // Error
+               case 1:
+                       console.error(data);
+                       
+                       break;
+               
+               // Warning
+               case 2:
+                       console.warn(data);
+                       
+                       break;
+               
+               // Information
+               case 3:
+                       console.info(data);
+                       
+                       break;
+               
+               // Default log level
+               default:
+                       console.log(data);
+                       
+                       break;
+       }
+       
+       return true;
+}
+
+// Gets the current Jappix app. location
+function getJappixLocation() {
+       var url = window.location.href;
+       
+       // If the URL has variables, remove them
+       if(url.indexOf('?') != -1)
+               url = url.split('?')[0];
+       if(url.indexOf('#') != -1)
+               url = url.split('#')[0];
+       
+       // No "/" at the end
+       if(!url.match(/(.+)\/$/))
+               url += '/';
+       
+       return url;
+}
+
+// Removes spaces at the beginning & the end of a string
+function trim(str) {
+       return str.replace(/^\s+/g,'').replace(/\s+$/g,'');
+}
+
+// Adds a zero to a date when needed
+function padZero(i) {
+       // Negative number (without first 0)
+       if(i > -10 && i < 0)
+               return '-0' + (i * -1);
+       
+       // Positive number (without first 0)
+       if(i < 10 && i >= 0)
+               return '0' + i;
+       
+       // All is okay
+       return i;
+}
diff --git a/jappixmini/jappix/js/connection.js b/jappixmini/jappix/js/connection.js
new file mode 100644 (file)
index 0000000..85a718c
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+
+Jappix - An open social platform
+These are the connection JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 29/08/11
+
+*/
+
+// Does the user login
+var CURRENT_SESSION = false;
+
+function doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember) {
+       try {
+               // We remove the not completed class to avoid problems
+               $('#home .loginer input').removeClass('please-complete');
+               
+               // We add the login wait div
+               showGeneralWait();
+               
+               // We define the http binding parameters
+               oArgs = new Object();
+               
+               if(HOST_BOSH_MAIN)
+                       oArgs.httpbase = HOST_BOSH_MAIN;
+               else
+                       oArgs.httpbase = HOST_BOSH;
+               
+               // We create the new http-binding connection
+               con = new JSJaCHttpBindingConnection(oArgs);
+               
+               // And we handle everything that happen
+               setupCon(con);
+               
+               // Generate a resource
+               var random_resource = getDB('session', 'resource');
+               
+               if(!random_resource)
+                       random_resource = lResource + ' (' + (new Date()).getTime() + ')';
+               
+               // We retrieve what the user typed in the login inputs
+               oArgs = new Object();
+               oArgs.domain = trim(lServer);
+               oArgs.username = trim(lNick);
+               oArgs.resource = random_resource;
+               oArgs.pass = lPass;
+               oArgs.secure = true;
+               oArgs.xmllang = XML_LANG;
+               
+               // Store the resource (for reconnection)
+               setDB('session', 'resource', random_resource);
+               
+               // Generate a session XML to be stored
+               session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
+               
+               // Save the session parameters (for reconnect if network issue)
+               CURRENT_SESSION = session_xml;
+               
+               // Remember me?
+               if(lRemember)
+                       setDB('remember', 'session', 1);
+               
+               // We store the infos of the user into the data-base
+               setDB('priority', 1, lPriority);
+               
+               // We connect !
+               con.connect(oArgs);
+               
+               // Change the page title
+               pageTitle('wait');
+               
+               logThis('Jappix is connecting...', 3);
+       }
+       
+       catch(e) {
+               // Logs errors
+               logThis('Error while logging in: ' + e, 1);
+               
+               // Reset Jappix
+               destroyTalkPage();
+               
+               // Open an unknown error
+               openThisError(2);
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+// Handles the user registration
+function handleRegistered() {
+       logThis('A new account has been registered.', 3);
+       
+       // We remove the waiting image
+       removeGeneralWait();
+       
+       // Reset the title
+       pageTitle('home');
+       
+       // We show the success information
+       $('#home .registerer .success').fadeIn('fast');
+       
+       // We quit the session
+       logout();
+}
+
+// Does the user registration
+function doRegister(username, domain, pass) {
+       logThis('Trying to register an account...', 3);
+       
+       try {
+               // We define the http binding parameters
+               oArgs = new Object();
+               
+               if(HOST_BOSH_MAIN)
+                       oArgs.httpbase = HOST_BOSH_MAIN;
+               else
+                       oArgs.httpbase = HOST_BOSH;
+               
+               // We create the new http-binding connection
+               con = new JSJaCHttpBindingConnection(oArgs);
+               
+               // We setup the connection !
+               con.registerHandler('onconnect', handleRegistered);
+               con.registerHandler('onerror', handleError);
+               
+               // We retrieve what the user typed in the register inputs
+               oArgs = new Object();
+               oArgs.domain = trim(domain);
+               oArgs.username = trim(username);
+               oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
+               oArgs.pass = pass;
+               oArgs.register = true;
+               oArgs.secure = true;
+               oArgs.xmllang = XML_LANG;
+               
+               con.connect(oArgs);
+               
+               // We change the registered information text
+               $('#home .homediv.registerer').append(
+                       '<div class="info success">' + 
+                               _e("You have been registered, here is your XMPP address:") + ' <b>' + con.username.htmlEnc() + '@' + con.domain.htmlEnc() + '</b> - <a href="#">' + _e("Login") + '</a>' + 
+                       '</div>'
+               );
+               
+               // Login link
+               $('#home .homediv.registerer .success a').click(function() {
+                       return doLogin(con.username, con.domain, con.pass, con.resource, '10', false);
+               });
+               
+               // Show the waiting image
+               showGeneralWait();
+               
+               // Change the page title
+               pageTitle('wait');
+       }
+       
+       catch(e) {
+               // Logs errors
+               logThis(e, 1);
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+// Does the user anonymous login
+function doAnonymous() {
+       logThis('Trying to login anonymously...', 3);
+       
+       var aPath = '#home .anonymouser ';
+       var room = $(aPath + '.room').val();
+       var nick = $(aPath + '.nick').val();
+       
+       // If the form is correctly completed
+       if(room && nick) {
+               // We remove the not completed class to avoid problems
+               $('#home .anonymouser input').removeClass('please-complete');
+               
+               // Redirect the user to the anonymous room
+               window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
+       }
+       
+       // We check if the form is entirely completed
+       else {
+               $(aPath + 'input[type=text]').each(function() {
+                       var select = $(this);
+                       
+                       if(!select.val())
+                               $(document).oneTime(10, function() {
+                                       select.addClass('please-complete').focus();
+                               });
+                       else
+                               select.removeClass('please-complete');  
+               });
+       }
+       
+       return false;
+}
+
+// Handles the user connected event
+var CONNECTED = false;
+
+function handleConnected() {
+       logThis('Jappix is now connected.', 3);
+       
+       // Connection markers
+       CONNECTED = true;
+       RECONNECT_TRY = 0;
+       RECONNECT_TIMER = 0;
+       
+       // We hide the home page
+       $('#home').hide();
+       
+       // Not resumed?
+       if(!RESUME) {
+               // Remember the session?
+               if(getDB('remember', 'session'))
+                       setPersistent('session', 1, CURRENT_SESSION);
+               
+               // We show the chatting app.
+               createTalkPage();
+               
+               // We reset the homepage
+               switchHome('default');
+               
+               // We get all the other things
+               getEverything();
+               
+               // Set last activity stamp
+               LAST_ACTIVITY = getTimeStamp();
+       }
+       
+       // Resumed
+       else {
+               // Send our presence
+               presenceSend();
+               
+               // Change the title
+               updateTitle();
+       }
+       
+       // Remove the waiting item
+       removeGeneralWait();
+}
+
+// Handles the user disconnected event
+function handleDisconnected() {
+       logThis('Jappix is now disconnected.', 3);
+       
+       // Normal disconnection
+       if(!CURRENT_SESSION && !CONNECTED)
+               destroyTalkPage();
+}
+
+// Setups the normal connection
+function setupCon(con) {
+       // We setup all the necessary handlers for the connection
+       con.registerHandler('message', handleMessage);
+       con.registerHandler('presence', handlePresence);
+       con.registerHandler('iq', handleIQ);
+       con.registerHandler('onconnect', handleConnected);
+       con.registerHandler('onerror', handleError);
+       con.registerHandler('ondisconnect', handleDisconnected);
+}
+
+// Logouts from the server
+function logout() {
+       // We are not connected
+       if(!isConnected())
+               return false;
+       
+       // Disconnect from the XMPP server
+       con.disconnect();
+       
+       logThis('Jappix is disconnecting...', 3);
+}
+
+// Terminates a session
+function terminate() {
+       if(!isConnected())
+               return;
+       
+       // Clear temporary session storage
+       resetConMarkers();
+       
+       // Show the waiting item (useful if BOSH is sloooow)
+       showGeneralWait();
+       
+       // Change the page title
+       pageTitle('wait');
+       
+       // Disconnect from the XMPP server
+       logout();
+}
+
+// Quitss a session
+function quit() {
+       if(!isConnected())
+               return;
+       
+       // We show the waiting image
+       showGeneralWait();
+       
+       // Change the page title
+       pageTitle('wait');
+       
+       // We disconnect from the XMPP server
+       logout();
+}
+
+// Creates the reconnect pane
+var RECONNECT_TRY = 0;
+var RECONNECT_TIMER = 0;
+
+function createReconnect(mode) {
+       logThis('This is not a normal disconnection, show the reconnect pane...', 1);
+       
+       // Reconnect pane not yet displayed?
+       if(!exists('#reconnect')) {
+               // Blur the focused input/textarea/select
+               $('input, select, textarea').blur();
+               
+               // Create the HTML code
+               var html = '<div id="reconnect" class="lock">' + 
+                               '<div class="pane">' + 
+                                       _e("Due to a network issue, you were disconnected. What do you want to do now?");
+               
+               // Can we cancel reconnection?
+               if(mode == 'normal')
+                       html += '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>';
+               
+               html += '<a href="#" class="finish reconnect">' + _e("Reconnect") + '</a>' + 
+                       '</div></div>';
+               
+               // Append the code
+               $('body').append(html);
+               
+               // Click events
+               if(mode == 'normal')
+                       $('#reconnect a.finish.cancel').click(function() {
+                               return cancelReconnect();
+                       });
+               
+               $('#reconnect a.finish.reconnect').click(function() {
+                       return acceptReconnect(mode);
+               });
+               
+               // Try to reconnect automatically after a while
+               if(RECONNECT_TRY < 5)
+                       RECONNECT_TIMER = 5 + (5 * RECONNECT_TRY);
+               else
+                       RECONNECT_TIMER = 120;
+               
+               // Change the try number
+               RECONNECT_TRY++;
+               
+               // Fire the event!
+               $('#reconnect a.finish.reconnect').everyTime('1s', function() {
+                       // We can reconnect!
+                       if(RECONNECT_TIMER == 0)
+                               return acceptReconnect(mode);
+                       
+                       // Button text
+                       if(RECONNECT_TIMER <= 10)
+                               $(this).text(_e("Reconnect") + ' (' + RECONNECT_TIMER + ')');
+                       
+                       // Remove 1 second
+                       RECONNECT_TIMER--;
+               });
+               
+               // Page title
+               updateTitle();
+       }
+}
+
+// Reconnects the user if he was disconnected (network issue)
+var RESUME = false;
+
+function acceptReconnect(mode) {
+       logThis('Trying to reconnect the user...', 3);
+       
+       // Resume marker
+       RESUME = true;
+       
+       // Show waiting item
+       showGeneralWait();
+       
+       // Reset some various stuffs
+       var groupchats = '#page-engine .page-engine-chan[data-type=groupchat]';
+       $(groupchats + ' .list .role').hide();
+       $(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
+       $(groupchats).attr('data-initial', 'false');
+       
+       // Stop the timer
+       $('#reconnect a.finish.reconnect').stopTime();
+       
+       // Remove the reconnect pane
+       $('#reconnect').remove();
+       
+       // Try to login again
+       if(mode == 'normal')
+               loginFromSession(XMLFromString(CURRENT_SESSION));
+       else if(mode == 'anonymous')
+               anonymousLogin(HOST_ANONYMOUS);
+       
+       return false;
+}
+
+// Cancel the reconnection of user account (network issue)
+function cancelReconnect() {
+       logThis('User has canceled automatic reconnection...', 3);
+       
+       // Stop the timer
+       $('#reconnect a.finish.reconnect').stopTime();
+       
+       // Remove the reconnect pane
+       $('#reconnect').remove();
+       
+       // Destroy the talk page
+       destroyTalkPage();
+       
+       // Renitialize the previous session parameters
+       resetConMarkers();
+       
+       return false;
+}
+
+// Clears session reminder database
+function clearLastSession() {
+       // Clear temporary storage
+       resetConMarkers();
+       
+       // Clear persistent storage
+       if($(XMLFromString(getPersistent('session', 1))).find('stored').text() == 'true')
+               removePersistent('session', 1);
+}
+
+// Resets the connection markers
+function resetConMarkers() {
+       CURRENT_SESSION = false;
+       CONNECTED = false;
+       RESUME = false;
+       RECONNECT_TRY = 0;
+       RECONNECT_TIMER = 0;
+}
+
+// Logins from a saved session
+function loginFromSession(data) {
+       // Select the data
+       var session = $(data);
+       
+       // Fire the login event
+       doLogin(
+               session.find('username').text(),
+               session.find('domain').text(),
+               session.find('password').text(),
+               session.find('resource').text(),
+               session.find('priority').text(),
+               false
+       );
+}
+
+// Quits a session normally
+function normalQuit() {
+       // Reset our database
+       clearLastSession();
+       
+       // We quit the current session
+       quit();
+       
+       // We show an info
+       openThisInfo(3);
+       
+       return false;
+}
+
+// Gets all the users stuffs
+function getEverything() {
+       getFeatures();
+       getRoster();
+       listPrivacy();
+       getStorage(NS_ROSTERNOTES);
+}
+
+// Plugin launcher
+function launchConnection() {
+       // Logouts when Jappix is closed
+       $(window).bind('beforeunload', terminate);
+       
+       // Nothing to do when anonymous!
+       if(isAnonymous())
+               return;
+       
+       // Try to resume a stored session, if not anonymous
+       var session = XMLFromString(getPersistent('session', 1));
+       
+       if($(session).find('stored').text() == 'true') {
+               // Hide the homepage
+               $('#home').hide();
+               
+               // Show the waiting icon
+               showGeneralWait();
+               
+               // Login!
+               loginFromSession(session);
+               
+               logThis('Saved session found, resuming it...', 3);
+       }
+       
+       // Not connected, maybe a XMPP link is submitted?
+       else if((parent.location.hash != '#OK') && LINK_VARS['x']) {
+               switchHome('loginer');
+               
+               logThis('A XMPP link is set, switch to login page.', 3);
+       }
+}
+
+// Launch this plugin!
+$(document).ready(launchConnection);
diff --git a/jappixmini/jappix/js/constants.js b/jappixmini/jappix/js/constants.js
new file mode 100644 (file)
index 0000000..bc59bd7
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+
+Jappix - An open social platform
+These are the constants JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Stefan Strigler, Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// XMPP XMLNS attributes
+var NS_PROTOCOL =     'http://jabber.org/protocol/';
+var NS_FEATURES =     'http://jabber.org/features/';
+var NS_CLIENT =       'jabber:client';
+var NS_IQ =           'jabber:iq:';
+var NS_X =            'jabber:x:';
+var NS_IETF =         'urn:ietf:params:xml:ns:xmpp-';
+var NS_XMPP =         'urn:xmpp:';
+
+var NS_STORAGE =      'storage:';
+var NS_BOOKMARKS =    NS_STORAGE + 'bookmarks';
+var NS_ROSTERNOTES =  NS_STORAGE + 'rosternotes';
+
+var NS_JAPPIX =       'jappix:';
+var NS_INBOX =        NS_JAPPIX + 'inbox';
+var NS_OPTIONS =      NS_JAPPIX + 'options';
+
+var NS_DISCO_ITEMS =  NS_PROTOCOL + 'disco#items';
+var NS_DISCO_INFO =   NS_PROTOCOL + 'disco#info';
+var NS_VCARD =        'vcard-temp';
+var NS_VCARD_P =      NS_VCARD + ':x:update';
+var NS_AUTH =         NS_IQ + 'auth';
+var NS_AUTH_ERROR =   NS_IQ + 'auth:error';
+var NS_REGISTER =     NS_IQ + 'register';
+var NS_SEARCH =       NS_IQ + 'search';
+var NS_ROSTER =       NS_IQ + 'roster';
+var NS_PRIVACY =      NS_IQ + 'privacy';
+var NS_PRIVATE =      NS_IQ + 'private';
+var NS_VERSION =      NS_IQ + 'version';
+var NS_TIME =         NS_IQ + 'time';
+var NS_LAST =         NS_IQ + 'last';
+var NS_IQDATA =       NS_IQ + 'data';
+var NS_XDATA =        NS_X + 'data';
+var NS_IQOOB =        NS_IQ + 'oob';
+var NS_XOOB =         NS_X + 'oob';
+var NS_DELAY =        NS_X + 'delay';
+var NS_EXPIRE =       NS_X + 'expire';
+var NS_EVENT =        NS_X + 'event';
+var NS_XCONFERENCE =  NS_X + 'conference';
+var NS_STATS =        NS_PROTOCOL + 'stats';
+var NS_MUC =          NS_PROTOCOL + 'muc';
+var NS_MUC_USER =     NS_MUC + '#user';
+var NS_MUC_ADMIN =    NS_MUC + '#admin';
+var NS_MUC_OWNER =    NS_MUC + '#owner';
+var NS_MUC_CONFIG =   NS_MUC + '#roomconfig';
+var NS_PUBSUB =       NS_PROTOCOL + 'pubsub';
+var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
+var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
+var NS_PUBSUB_NMI =   NS_PUBSUB + '#node-meta-info';
+var NS_PUBSUB_NC =    NS_PUBSUB + '#node_config';
+var NS_PUBSUB_RI =    NS_PUBSUB + '#retrieve-items';
+var NS_COMMANDS =     NS_PROTOCOL + 'commands';
+var NS_BOSH =         NS_PROTOCOL + 'httpbind';
+var NS_STREAM =       'http://etherx.jabber.org/streams';
+var NS_URN_TIME =     NS_XMPP + 'time';
+var NS_URN_PING =     NS_XMPP + 'ping';
+var NS_URN_ADATA =    NS_XMPP + 'avatar:data';
+var NS_URN_AMETA =    NS_XMPP + 'avatar:metadata';
+var NS_URN_MBLOG =    NS_XMPP + 'microblog:0';
+var NS_URN_INBOX =    NS_XMPP + 'inbox';
+var NS_URN_ARCHIVE =  NS_XMPP + 'archive';
+var NS_URN_AR_PREF =  NS_URN_ARCHIVE + ':pref';
+var NS_URN_AR_AUTO =  NS_URN_ARCHIVE + ':auto';
+var NS_URN_AR_MANUAL =  NS_URN_ARCHIVE + ':manual';
+var NS_URN_AR_MANAGE =  NS_URN_ARCHIVE + ':manage';
+var NS_URN_DELAY =    NS_XMPP + 'delay';
+var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
+var NS_RSM =          NS_PROTOCOL + 'rsm';
+var NS_IPV6 =         'ipv6';
+var NS_XHTML =        'http://www.w3.org/1999/xhtml';
+var NS_XHTML_IM =     NS_PROTOCOL + 'xhtml-im';
+var NS_CHATSTATES =   NS_PROTOCOL + 'chatstates';
+var NS_HTTP_AUTH =    NS_PROTOCOL + 'http-auth';
+var NS_ROSTERX =      NS_PROTOCOL + 'rosterx';
+var NS_MOOD =         NS_PROTOCOL + 'mood';
+var NS_ACTIVITY =     NS_PROTOCOL + 'activity';
+var NS_TUNE =         NS_PROTOCOL + 'tune';
+var NS_GEOLOC =       NS_PROTOCOL + 'geoloc';
+var NS_NICK =         NS_PROTOCOL + 'nick';
+var NS_NOTIFY =       '+notify';
+var NS_CAPS =         NS_PROTOCOL + 'caps';
+var NS_ATOM =         'http://www.w3.org/2005/Atom';
+
+var NS_STANZAS =      NS_IETF + 'stanzas';
+var NS_STREAMS =      NS_IETF + 'streams';
+
+var NS_TLS =          NS_IETF + 'tls';
+var NS_SASL =         NS_IETF + 'sasl';
+var NS_SESSION =      NS_IETF + 'session';
+var NS_BIND =         NS_IETF + 'bind';
+
+var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
+var NS_FEATURE_IQREGISTER = NS_FEATURES + 'iq-register';
+var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
+
+var NS_COMPRESS =     NS_PROTOCOL + 'compress';
+
+// Available locales
+var LOCALES_AVAILABLE_ID = new Array();
+var LOCALES_AVAILABLE_NAMES = new Array();
+
+// XML lang
+var XML_LANG = null;
+
+// Jappix parameters
+var JAPPIX_STATIC = null;
+var JAPPIX_VERSION = null;
+var JAPPIX_MAX_FILE_SIZE = null;
+var JAPPIX_MAX_UPLOAD = null;
+
+// Jappix main configuration
+var SERVICE_NAME = null;
+var SERVICE_DESC = null;
+var JAPPIX_RESOURCE = null;
+var LOCK_HOST = null;
+var ANONYMOUS = null;
+var REGISTRATION = null;
+var BOSH_PROXY = null;
+var MANAGER_LINK = null;
+var GROUPCHATS_JOIN = null;
+var ENCRYPTION = null;
+var HTTPS_STORAGE = null;
+var HTTPS_FORCE = null;
+var COMPRESSION = null;
+var MULTI_FILES = null;
+var DEVELOPER = null;
+
+// Jappix hosts configuration
+var HOST_MAIN = null;
+var HOST_MUC = null;
+var HOST_PUBSUB = null;
+var HOST_VJUD = null;
+var HOST_ANONYMOUS = null;
+var HOST_BOSH = null;
+var HOST_BOSH_MAIN = null;
+var HOST_BOSH_MINI = null;
+var HOST_STATIC = null;
+var HOST_UPLOAD = null;
+
+// Anonymous mode
+var ANONYMOUS_ROOM = null;
+var ANONYMOUS_NICK = null;
+
+// Node parameters
+var JAPPIX_LOCATION = getJappixLocation();
+
+// XMPP error stanzas
+function STANZA_ERROR(code, type, cond) {
+       if (window == this)
+               return new STANZA_ERROR(code, type, cond);
+       
+       this.code = code;
+       this.type = type;
+       this.cond = cond;
+}
+
+var ERR_BAD_REQUEST =
+       STANZA_ERROR('400', 'modify', 'bad-request');
+var ERR_CONFLICT =
+       STANZA_ERROR('409', 'cancel', 'conflict');
+var ERR_FEATURE_NOT_IMPLEMENTED =
+       STANZA_ERROR('501', 'cancel', 'feature-not-implemented');
+var ERR_FORBIDDEN =
+       STANZA_ERROR('403', 'auth',   'forbidden');
+var ERR_GONE =
+       STANZA_ERROR('302', 'modify', 'gone');
+var ERR_INTERNAL_SERVER_ERROR =
+       STANZA_ERROR('500', 'wait',   'internal-server-error');
+var ERR_ITEM_NOT_FOUND =
+       STANZA_ERROR('404', 'cancel', 'item-not-found');
+var ERR_JID_MALFORMED =
+       STANZA_ERROR('400', 'modify', 'jid-malformed');
+var ERR_NOT_ACCEPTABLE =
+       STANZA_ERROR('406', 'modify', 'not-acceptable');
+var ERR_NOT_ALLOWED =
+       STANZA_ERROR('405', 'cancel', 'not-allowed');
+var ERR_NOT_AUTHORIZED =
+       STANZA_ERROR('401', 'auth',   'not-authorized');
+var ERR_PAYMENT_REQUIRED =
+       STANZA_ERROR('402', 'auth',   'payment-required');
+var ERR_RECIPIENT_UNAVAILABLE =
+       STANZA_ERROR('404', 'wait',   'recipient-unavailable');
+var ERR_REDIRECT =
+       STANZA_ERROR('302', 'modify', 'redirect');
+var ERR_REGISTRATION_REQUIRED =
+       STANZA_ERROR('407', 'auth',   'registration-required');
+var ERR_REMOTE_SERVER_NOT_FOUND =
+       STANZA_ERROR('404', 'cancel', 'remote-server-not-found');
+var ERR_REMOTE_SERVER_TIMEOUT =
+       STANZA_ERROR('504', 'wait',   'remote-server-timeout');
+var ERR_RESOURCE_CONSTRAINT =
+       STANZA_ERROR('500', 'wait',   'resource-constraint');
+var ERR_SERVICE_UNAVAILABLE =
+       STANZA_ERROR('503', 'cancel', 'service-unavailable');
+var ERR_SUBSCRIPTION_REQUIRED =
+       STANZA_ERROR('407', 'auth',   'subscription-required');
+var ERR_UNEXPECTED_REQUEST =
+       STANZA_ERROR('400', 'wait',   'unexpected-request');
diff --git a/jappixmini/jappix/js/dataform.js b/jappixmini/jappix/js/dataform.js
new file mode 100644 (file)
index 0000000..7fbea89
--- /dev/null
@@ -0,0 +1,921 @@
+/*
+
+Jappix - An open social platform
+These are the dataform JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/08/11
+
+*/
+
+// Gets the defined dataform elements
+function dataForm(host, type, node, action, target) {
+       // Clean the current session
+       cleanDataForm(target);
+       
+       // We tell the user that a search has been launched
+       $('#' + target + ' .wait').show();
+       
+       // If we have enough data
+       if(host && type) {
+               // Generate a session ID
+               var sessionID = Math.round(100000.5 + (((900000.49999) - (100000.5)) * Math.random()));
+               var id = target + '-' + sessionID + '-' + genID();
+               $('.' + target + '-results').attr('data-session', target + '-' + sessionID);
+               
+               // We request the service item
+               var iq = new JSJaCIQ();
+               iq.setID(id);
+               iq.setTo(host);
+               iq.setType('get');
+               
+               // MUC admin query
+               if(type == 'muc') {
+                       iq.setQuery(NS_MUC_OWNER);
+                       con.send(iq, handleDataFormMuc);
+               }
+               
+               // Browse query
+               else if(type == 'browse') {
+                       var iqQuery = iq.setQuery(NS_DISCO_ITEMS);
+                       
+                       if(node)
+                               iqQuery.setAttribute('node', node);
+                       
+                       con.send(iq, handleDataFormBrowse);
+               }
+               
+               // Command
+               else if(type == 'command') {
+                       var items;
+                       
+                       if(node)
+                               items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS});
+                       
+                       else {
+                               items = iq.setQuery(NS_DISCO_ITEMS);
+                               items.setAttribute('node', NS_COMMANDS);
+                       }
+                       
+                       if(action && node) {
+                               iq.setType('set');
+                               items.setAttribute('action', action);
+                       }
+                       
+                       con.send(iq, handleDataFormCommand);
+               }
+               
+               // Search query
+               else if(type == 'search') {
+                       iq.setQuery(NS_SEARCH);
+                       con.send(iq, handleDataFormSearch);
+               }
+               
+               // Subscribe query
+               else if(type == 'subscribe') {
+                       iq.setQuery(NS_REGISTER);
+                       con.send(iq, handleDataFormSubscribe);
+               }
+               
+               // Join
+               else if(type == 'join') {
+                       if(target == 'discovery')
+                               closeDiscovery();
+                       
+                       checkChatCreate(host, 'groupchat');
+               }
+       }
+       
+       return false;
+}
+
+// Sends a given dataform
+function sendDataForm(type, action, x_type, id, xid, node, sessionid, target) {
+       // Path
+       var pathID = '#' + target + ' .results[data-session=' + id + ']';
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setTo(xid);
+       iq.setType('set');
+       
+       // Set the correct query
+       var query;
+       
+       if(type == 'subscribe')
+               iqQuery = iq.setQuery(NS_REGISTER);
+       else if(type == 'search')
+               iqQuery = iq.setQuery(NS_SEARCH);
+       else if(type == 'command')
+               iqQuery = iq.appendNode('command', {'xmlns': NS_COMMANDS, 'node': node, 'sessionid': sessionid, 'action': action});
+       else if(type == 'x')
+               iqQuery = iq.setQuery(NS_MUC_OWNER);
+       
+       // Build the XML document
+       if(action != 'cancel') {
+               // No X node
+               if(exists('input.register-special') && (type == 'subscribe')) {
+                       $('input.register-special').each(function() {
+                               var iName = $(this).attr('name');
+                               var iValue = $(this).val();
+                               
+                               iqQuery.appendChild(iq.buildNode(iName, {'xmlns': NS_REGISTER}, iValue));
+                       });
+               }
+               
+               // Can create the X node
+               else {
+                       var iqX = iqQuery.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': x_type}));
+                       
+                       // Each input
+                       $(pathID + ' .oneresult input, ' + pathID + ' .oneresult textarea, ' + pathID + ' .oneresult select').each(function() {
+                               // Get the current input value
+                               var iVar = $(this).attr('name');
+                               var iType = $(this).attr('data-type');
+                               var iValue = $(this).val();
+                               
+                               // Build a new field node
+                               var field = iqX.appendChild(iq.buildNode('field', {'var': iVar, 'type': iType, 'xmlns': NS_XDATA}));
+                               
+                               // Boolean input?
+                               if(iType == 'boolean') {
+                                       if($(this).filter(':checked').size())
+                                               iValue = '1';
+                                       else
+                                               iValue = '0';
+                               }
+                               
+                               // JID-multi input?
+                               if(iType == 'jid-multi') {
+                                       // Values array
+                                       var xid_arr = [iValue];
+                                       var xid_check = [];
+                                       
+                                       // Try to split it
+                                       if(iValue.indexOf(',') != -1)
+                                               xid_arr = iValue.split(',');
+                                       
+                                       // Append each value to the XML document
+                                       for(i in xid_arr) {
+                                               // Get the current value
+                                               xid_current = trim(xid_arr[i]);
+                                               
+                                               // No current value?
+                                               if(!xid_current)
+                                                       continue;
+                                               
+                                               // Add the current value
+                                               if(!existArrayValue(xid_check, xid_current)) {
+                                                       xid_check.push(xid_current);
+                                                       field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, xid_current));
+                                               }
+                                       }
+                               }
+                               
+                               // List-multi selector?
+                               else if(iType == 'list-multi') {
+                                       // Any value?
+                                       if(iValue && iValue.length) {
+                                               for(i in iValue)
+                                                       field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue[i]));
+                                       }
+                               }
+                               
+                               // Other inputs?
+                               else
+                                       field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue));
+                       });
+               }
+       }
+       
+       // Clean the current session
+       cleanDataForm(target);
+       
+       // Show the waiting item
+       $('#' + target + ' .wait').show();
+       
+       // Change the ID of the current discovered item
+       var iqID = target + '-' + genID();
+       $('#' + target + ' .' + target + '-results').attr('data-session', iqID);
+       iq.setID(iqID);
+       
+       // Send the IQ
+       if(type == 'subscribe')
+               con.send(iq, handleDataFormSubscribe);
+       else if(type == 'search')
+               con.send(iq, handleDataFormSearch);
+       else if(type == 'command')
+               con.send(iq, handleDataFormCommand);
+       else
+               con.send(iq);
+       
+       return false;
+}
+
+// Displays the good dataform buttons
+function buttonsDataForm(type, action, id, xid, node, sessionid, target, pathID) {
+       // No need to use buttons?
+       if(type == 'muc')
+               return;
+       
+       // Override the "undefined" output
+       if(!id)
+               id = '';
+       if(!xid)
+               xid = '';
+       if(!node)
+               node = '';
+       if(!sessionid)
+               sessionid = '';
+       
+       // We generate the buttons code
+       var buttonsCode = '<div class="oneresult ' + target + '-oneresult ' + target + '-formtools">';
+       
+       if(action == 'submit') {
+               if((target == 'adhoc') && (type == 'command')) {
+                       buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'execute\', \'submit\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Submit") + '</a>';
+                       
+                       // When keyup on one text input
+                       $(pathID + ' input').keyup(function(e) {
+                               if(e.keyCode == 13) {
+                                       sendDataForm(type, 'execute', 'submit', id, xid, node, sessionid, target);
+                                       
+                                       return false;
+                               }
+                       });
+               }
+               
+               else {
+                       buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'submit\', \'submit\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Submit") + '</a>';
+                       
+                       // When keyup on one text input
+                       $(pathID + ' input').keyup(function(e) {
+                               if(e.keyCode == 13) {
+                                       sendDataForm(type, 'submit', 'submit', id, xid, node, sessionid, target);
+                                       
+                                       return false;
+                               }
+                       });
+               }
+       }
+       
+       if((action == 'submit') && (type != 'subscribe') && (type != 'search'))
+               buttonsCode += '<a href="#" class="submit" onclick="return sendDataForm(\'' + encodeOnclick(type) + '\', \'cancel\', \'cancel\', \'' + encodeOnclick(id) + '\', \'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(sessionid) + '\', \'' + encodeOnclick(target) + '\');">' + _e("Cancel") + '</a>';
+       
+       if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery'))
+               buttonsCode += '<a href="#" class="back" onclick="return startDiscovery();">' + _e("Close") + '</a>';
+       
+       if((action == 'back') && ((target == 'welcome') || (target == 'directory')))
+               buttonsCode += '<a href="#" class="back" onclick="return dataForm(HOST_VJUD, \'search\', \'\', \'\', \'' + target + '\');">' + _e("Previous") + '</a>';
+       
+       if((action == 'back') && (target == 'adhoc'))
+               buttonsCode += '<a href="#" class="back" onclick="return dataForm(\'' + encodeOnclick(xid) + '\', \'command\', \'\', \'\', \'adhoc\');">' + _e("Previous") + '</a>';
+       
+       buttonsCode += '</div>';
+       
+       // We display the buttons code
+       $(pathID).append(buttonsCode);
+       
+       // If no submit link, lock the form
+       if(!exists(pathID + ' a.submit'))
+               $(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true);
+}
+
+// Handles the MUC dataform
+function handleDataFormMuc(iq) {
+       handleErrorReply(iq);
+       handleDataFormContent(iq, 'muc');
+}
+
+// Handles the browse dataform
+function handleDataFormBrowse(iq) {
+       handleErrorReply(iq);
+       handleDataFormContent(iq, 'browse');
+}
+
+// Handles the command dataform
+function handleDataFormCommand(iq) {
+       handleErrorReply(iq);
+       handleDataFormContent(iq, 'command');
+}
+
+// Handles the subscribe dataform
+function handleDataFormSubscribe(iq) {
+       handleErrorReply(iq);
+       handleDataFormContent(iq, 'subscribe');
+}
+
+// Handles the search dataform
+function handleDataFormSearch(iq) {
+       handleErrorReply(iq);
+       handleDataFormContent(iq, 'search');
+}
+
+// Handles the dataform content
+function handleDataFormContent(iq, type) {
+       // Get the ID
+       var sID = iq.getID();
+       
+       // Get the target
+       var splitted = sID.split('-');
+       var target = splitted[0];
+       var sessionID = target + '-' + splitted[1];
+       var from = fullXID(getStanzaFrom(iq));
+       var pathID = '#' + target + ' .results[data-session=' + sessionID + ']';
+       
+       // If an error occured
+       if(!iq || (iq.getType() != 'result'))
+               noResultDataForm(pathID);
+       
+       // If we got something okay
+       else {
+               var handleXML = iq.getNode();
+               
+               if(type == 'browse') {
+                       if($(handleXML).find('item').attr('jid')) {
+                               // Get the query node
+                               var queryNode = $(handleXML).find('query').attr('node');
+                               
+                               $(handleXML).find('item').each(function() {
+                                       // We parse the received xml
+                                       var itemHost = $(this).attr('jid');
+                                       var itemNode = $(this).attr('node');
+                                       var itemName = $(this).attr('name');
+                                       var itemHash = hex_md5(itemHost);
+                                       
+                                       // Node
+                                       if(itemNode)
+                                               $(pathID).append(
+                                                       '<div class="oneresult ' + target + '-oneresult" onclick="return dataForm(\'' + encodeOnclick(itemHost) + '\', \'browse\', \'' + encodeOnclick(itemNode) + '\', \'\', \'' + encodeOnclick(target) + '\');">' + 
+                                                               '<div class="one-name">' + itemNode.htmlEnc() + '</div>' + 
+                                                       '</div>'
+                                               );
+                                       
+                                       // Item
+                                       else if(queryNode && itemName)
+                                               $(pathID).append(
+                                                       '<div class="oneresult ' + target + '-oneresult">' + 
+                                                               '<div class="one-name">' + itemName.htmlEnc() + '</div>' + 
+                                                       '</div>'
+                                               );
+                                       
+                                       // Item with children
+                                       else {
+                                               // We display the waiting element
+                                               $(pathID + ' .disco-wait .disco-category-title').after(
+                                                       '<div class="oneresult ' + target + '-oneresult ' + itemHash + '">' + 
+                                                               '<div class="one-icon loading talk-images"></div>' + 
+                                                               '<div class="one-host">' + itemHost + '</div>' + 
+                                                               '<div class="one-type">' + _e("Requesting this service...") + '</div>' + 
+                                                       '</div>'
+                                               );
+                                               
+                                               // We display the category
+                                               $('#' + target + ' .disco-wait').show();
+                                               
+                                               // We ask the server what's the service type
+                                               getDataFormType(itemHost, itemNode, sessionID);
+                                       }
+                               });
+                       }
+                       
+                       // Else, there are no items for this query
+                       else
+                               noResultDataForm(pathID);
+               }
+               
+               else if((type == 'muc') || (type == 'search') || (type == 'subscribe') || ((type == 'command') && $(handleXML).find('command').attr('xmlns'))) {
+                       // Get some values
+                       var xCommand = $(handleXML).find('command');
+                       var bNode = xCommand.attr('node');
+                       var bSession = xCommand.attr('sessionid');
+                       var bStatus = xCommand.attr('status');
+                       var xRegister = $(handleXML).find('query[xmlns=' + NS_REGISTER + ']').text();
+                       var xElement = $(handleXML).find('x');
+                       
+                       // Search done
+                       if((xElement.attr('type') == 'result') && (type == 'search')) {
+                               var bPath = pathID;
+                               
+                               // Display the result
+                               $(handleXML).find('item').each(function() {
+                                       var bXID = $(this).find('field[var=jid] value:first').text();
+                                       var bName = $(this).find('field[var=fn] value:first').text();
+                                       var bCountry = $(this).find('field[var=ctry] value:first').text();
+                                       var dName = bName;
+                                       
+                                       // Override "undefined" value
+                                       if(!bXID)
+                                               bXID = '';
+                                       if(!bName)
+                                               bName = _e("Unknown name");
+                                       if(!bCountry)
+                                               bCountry = _e("Unknown country");
+                                       
+                                       // User hash
+                                       var bHash = hex_md5(bXID);
+                                       
+                                       // HTML code
+                                       var bHTML = '<div class="oneresult ' + target + '-oneresult ' + bHash + '">' + 
+                                                       '<div class="avatar-container">' + 
+                                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                                       '</div>' + 
+                                                       '<div class="one-fn">' + bName + '</div>' + 
+                                                       '<div class="one-ctry">' + bCountry + '</div>' + 
+                                                       '<div class="one-jid">' + bXID + '</div>' + 
+                                                       '<div class="buttons-container">';
+                                       
+                                       // The buddy is not in our buddy list?
+                                       if(!exists('#buddy-list .buddy[data-xid=' + escape(bXID) + ']'))
+                                               bHTML += '<a href="#" class="one-add one-vjud one-button talk-images">' + _e("Add") + '</a>';
+                                       
+                                       // Chat button, if not in welcome/directory mode
+                                       if(target == 'discovery')
+                                               bHTML += '<a href="#" class="one-chat one-vjud one-button talk-images">' + _e("Chat") + '</a>';
+                                       
+                                       // Close the HTML element
+                                       bHTML += '</div></div>';
+                                       
+                                       $(bPath).append(bHTML);
+                                       
+                                       // Click events
+                                       $(bPath + ' .' + bHash + ' a').click(function() {
+                                               // Buddy add
+                                               if($(this).is('.one-add')) {
+                                                       $(this).hide();
+                                                       
+                                                       addThisContact(bXID, dName);
+                                               }
+                                               
+                                               // Buddy chat
+                                               if($(this).is('.one-chat')) {
+                                                       if(target == 'discovery')
+                                                               closeDiscovery();
+                                                       
+                                                       checkChatCreate(bXID , 'chat', '', '', dName);
+                                               }
+                                               
+                                               return false;
+                                       });
+                                       
+                                       // Get the user's avatar
+                                       if(bXID)
+                                               getAvatar(bXID, 'cache', 'true', 'forget');
+                               });
+                               
+                               // No result?
+                               if(!$(handleXML).find('item').size())
+                                       noResultDataForm(pathID);
+                               
+                               // Previous button
+                               buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID);
+                       }
+                       
+                       // Command to complete
+                       else if(xElement.attr('xmlns') || ((type == 'subscribe') && xRegister)) {
+                               // We display the elements
+                               fillDataForm(handleXML, sessionID);
+                               
+                               // We display the buttons
+                               if(bStatus != 'completed')
+                                       buttonsDataForm(type, 'submit', sessionID, from, bNode, bSession, target, pathID);
+                               else
+                                       buttonsDataForm(type, 'back', sessionID, from, bNode, bSession, target, pathID);
+                       }
+                       
+                       // Command completed or subscription done
+                       else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) {
+                               // Display the good text
+                               var cNote = $(xCommand).find('note');
+                               
+                               // Any note?
+                               if(cNote.size()) {
+                                       cNote.each(function() {
+                                               $(pathID).append(
+                                                       '<div class="onetitle ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
+                                               );
+                                       });
+                               }
+                               
+                               // Default text
+                               else
+                                       $(pathID).append('<div class="oneinstructions ' + target + '-oneresult">' + _e("Your form has been sent.") + '</div>');
+                               
+                               // Display the back button
+                               buttonsDataForm(type, 'back', sessionID, from, '', '', target, pathID);
+                               
+                               // Add the gateway to our roster if subscribed
+                               if(type == 'subscribe')
+                                       addThisContact(from);
+                       }
+                       
+                       // Command canceled
+                       else if((bStatus == 'canceled') && (type == 'command')) {
+                               if(target == 'discovery')
+                                       startDiscovery();
+                               else if(target == 'adhoc')
+                                       dataForm(from, 'command', '', '', 'adhoc');
+                       }
+                       
+                       // No items for this query
+                       else
+                               noResultDataForm(pathID);
+               }
+               
+               else if(type == 'command') {
+                       if($(handleXML).find('item').attr('jid')) {
+                               // We display the elements
+                               $(handleXML).find('item').each(function() {
+                                       // We parse the received xml
+                                       var itemHost = $(this).attr('jid');
+                                       var itemNode = $(this).attr('node');
+                                       var itemName = $(this).attr('name');
+                                       var itemHash = hex_md5(itemHost);
+                                       
+                                       // We display the waiting element
+                                       $(pathID).prepend(
+                                               '<div class="oneresult ' + target + '-oneresult ' + itemHash + '" onclick="return dataForm(\'' + encodeOnclick(itemHost) + '\', \'command\', \'' + encodeOnclick(itemNode) + '\', \'execute\', \'' + encodeOnclick(target) + '\');">' + 
+                                                       '<div class="one-name">' + itemName + '</div>' + 
+                                                       '<div class="one-next">»</div>' + 
+                                               '</div>'
+                                       );
+                               });
+                       }
+                       
+                       // Else, there are no items for this query
+                       else
+                               noResultDataForm(pathID);
+               }
+       }
+       
+       // Focus on the first input
+       $(document).oneTime(10, function() {
+               $(pathID + ' input:visible:first').focus();
+       });
+       
+       // Hide the wait icon
+       $('#' + target + ' .wait').hide();
+}
+
+// Fills the dataform elements
+function fillDataForm(xml, id) {
+       /* REF: http://xmpp.org/extensions/xep-0004.html */
+       
+       // Initialize new vars
+       var target = id.split('-')[0];
+       var pathID = '#' + target + ' .results[data-session=' + id + ']';
+       var selector, is_dataform;
+       
+       // Is it a dataform?
+       if($(xml).find('x[xmlns=' + NS_XDATA + ']').size())
+               is_dataform = true;
+       else
+               is_dataform = false;
+       
+       // Determines the good selector to use
+       if(is_dataform)
+               selector = $(xml).find('x[xmlns=' + NS_XDATA + ']');
+       else
+               selector = $(xml);
+       
+       // Form title
+       selector.find('title').each(function() {
+               $(pathID).append(
+                       '<div class="onetitle ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
+               );
+       });
+       
+       // Form instructions
+       selector.find('instructions').each(function() {
+               $(pathID).append(
+                       '<div class="oneinstructions ' + target + '-oneresult">' + $(this).text().htmlEnc() + '</div>'
+               );
+       });
+       
+       // Register?
+       if(!is_dataform) {
+               // Items to detect
+               var reg_names = [_e("Nickname"), _e("Name"), _e("Password"), _e("E-mail")];
+               var reg_ids = ['username', 'name', 'password', 'email'];
+               
+               // Append these inputs
+               for(a in reg_names) {
+                       selector.find(reg_ids[a]).each(function() {
+                               $(pathID).append(
+                                       '<div class="oneresult ' + target + '-oneresult">' + 
+                                               '<label>' + reg_names[a] + '</label>' + 
+                                               '<input name="' + reg_ids[a] + '" type="text" class="register-special dataform-i" />' + 
+                                       '</div>'
+                               );
+                       });
+               }
+               
+               return false;
+       }
+       
+       // Dataform?
+       selector.find('field').each(function() {
+               // We parse the received xml
+               var type = $(this).attr('type');
+               var label = $(this).attr('label');
+               var field = $(this).attr('var');
+               var value = $(this).find('value:first').text();
+               var required = '';
+               
+               // No value?
+               if(!field)
+                       return;
+               
+               // Required input?
+               if($(this).find('required').size())
+                       required = ' required=""';
+               
+               // Compatibility fix
+               if(!label)
+                       label = field;
+               
+               if(!type)
+                       type = '';
+               
+               // Generate some values
+               var input;
+               var hideThis = '';
+               
+               // Fixed field
+               if(type == 'fixed')
+                       $(pathID).append('<div class="oneinstructions">' + value.htmlEnc() + '</div>');
+               
+               else {
+                       // Hidden field
+                       if(type == 'hidden') {
+                               hideThis = ' style="display: none;"';
+                               input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="hidden" class="dataform-i" value="' + encodeQuotes(value) + '" ' + required + ' />';
+                       }
+
+                       // Boolean field
+                       else if(type == 'boolean') {
+                               var checked;
+                               
+                               if(value == '1')
+                                       checked = 'checked';
+                               else
+                                       checked = '';
+                               
+                               input = '<input name="' + encodeQuotes(field) + '" type="checkbox" data-type="' + encodeQuotes(type) + '" class="dataform-i df-checkbox" ' + checked + required + ' />';
+                       }
+                       
+                       // List-single/list-multi field
+                       else if((type == 'list-single') || (type == 'list-multi')) {
+                               var multiple = '';
+                               
+                               // Multiple options?
+                               if(type == 'list-multi')
+                                       multiple = ' multiple=""';
+                               
+                               // Append the select field
+                               input = '<select name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" class="dataform-i"' + required + multiple + '>';
+                               var selected;
+                               
+                               // Append the available options
+                               $(this).find('option').each(function() {
+                                       var nLabel = $(this).attr('label');
+                                       var nValue = $(this).find('value').text();
+                                       
+                                       // No label?
+                                       if(!nLabel)
+                                               nLabel = nValue;
+                                       
+                                       // If this is the selected value
+                                       if(nValue == value)
+                                               selected = 'selected';
+                                       else
+                                               selected = '';
+                                       
+                                       input += '<option ' + selected + ' value="' + encodeQuotes(nValue) + '">' + nLabel.htmlEnc() + '</option>';
+                               });
+                               
+                               input += '</select>';
+                       }
+                       
+                       // Text-multi field
+                       else if(type == 'text-multi')
+                               input = '<textarea rows="8" cols="60" data-type="' + encodeQuotes(type) + '" name="' + encodeQuotes(field) + '" class="dataform-i"' + required + '>' + value.htmlEnc() + '</textarea>';
+                       
+                       // JID-multi field
+                       else if(type == 'jid-multi') {
+                               // Put the XID into an array
+                               var xid_arr = [];
+                               
+                               $(this).find('value').each(function() {
+                                       var cValue = $(this).text();
+                                       
+                                       if(!existArrayValue(xid_arr, cValue))
+                                               xid_arr.push(cValue);
+                               });
+                               
+                               // Sort the array
+                               xid_arr.sort();
+                               
+                               // Create the input
+                               var xid_value = '';
+                               
+                               if(xid_arr.length) {
+                                       for(i in xid_arr) {
+                                               // Any pre-value
+                                               if(xid_value)
+                                                       xid_value += ', ';
+                                               
+                                               // Add the current XID
+                                               xid_value += xid_arr[i];
+                                       }
+                               }
+                               
+                               input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="text" class="dataform-i" value="' + encodeQuotes(xid_value) + '" placeholder="jack@jappix.com, jones@jappix.com"' + required + ' />';
+                       }
+                       
+                       // Other stuffs that are similar
+                       else {
+                               // Text-single field
+                               var iType = 'text';
+                               
+                               // Text-private field
+                               if(type == 'text-private')
+                                       iType = 'password';
+                               
+                               // JID-single field
+                               else if(type == 'jid-single')
+                                       iType = 'email';
+                               
+                               input = '<input name="' + encodeQuotes(field) + '" data-type="' + encodeQuotes(type) + '" type="' + iType + '" class="dataform-i" value="' + encodeQuotes(value) + '"' + required + ' />';
+                       }
+                       
+                       // Append the HTML markup for this field
+                       $(pathID).append(
+                               '<div class="oneresult ' + target + '-oneresult"' + hideThis + '>' + 
+                                       '<label>' + label.htmlEnc() + '</label>' + 
+                                       input + 
+                               '</div>'
+                       );
+               }
+       });
+       
+       return false;
+}
+
+// Gets the dataform type
+function getDataFormType(host, node, id) {
+       var iq = new JSJaCIQ();
+       iq.setID(id + '-' + genID());
+       iq.setTo(host);
+       iq.setType('get');
+       
+       var iqQuery = iq.setQuery(NS_DISCO_INFO);
+       
+       if(node)
+               iqQuery.setAttribute('node', node);
+       
+       con.send(iq, handleThisBrowse);
+}
+
+// Handles the browse stanza
+function handleThisBrowse(iq) {
+       /* REF: http://xmpp.org/registrar/disco-categories.html */
+       
+       var id = iq.getID();
+       var splitted = id.split('-');
+       var target = splitted[0];
+       var sessionID = target + '-' + splitted[1];
+       var from = fullXID(getStanzaFrom(iq));
+       var hash = hex_md5(from);
+       var handleXML = iq.getQuery();
+       var pathID = '#' + target + ' .results[data-session=' + sessionID + ']';
+       
+       // We first remove the waiting element
+       $(pathID + ' .disco-wait .' + hash).remove();
+       
+       if($(handleXML).find('identity').attr('type')) {
+               var category = $(handleXML).find('identity').attr('category');
+               var type = $(handleXML).find('identity').attr('type');
+               var named = $(handleXML).find('identity').attr('name');
+               
+               if(named)
+                       gName = named;
+               else
+                       gName = '';
+               
+               var one, two, three, four, five;
+               
+               // Get the features that this entity supports
+               var findFeature = $(handleXML).find('feature');
+               
+               for(i in findFeature) {
+                       var current = findFeature.eq(i).attr('var');
+                       
+                       switch(current) {
+                               case NS_SEARCH:
+                                       one = 1;
+                                       break;
+                               
+                               case NS_MUC:
+                                       two = 1;
+                                       break;
+                               
+                               case NS_REGISTER:
+                                       three = 1;
+                                       break;
+                               
+                               case NS_COMMANDS:
+                                       four = 1;
+                                       break;
+                               
+                               case NS_DISCO_ITEMS:
+                                       five = 1;
+                                       break;
+                               
+                               default:
+                                       break;
+                       }
+               }
+               
+               var buttons = Array(one, two, three, four, five);
+               
+               // We define the toolbox links depending on the supported features
+               var tools = '';
+               var aTools = Array('search', 'join', 'subscribe', 'command', 'browse');
+               var bTools = Array(_e("Search"), _e("Join"), _e("Subscribe"), _e("Command"), _e("Browse"));
+               
+               for(i in buttons) {
+                       if(buttons[i])
+                               tools += '<a href="#" class="one-button ' + aTools[i] + ' talk-images" onclick="return dataForm(\'' + encodeOnclick(from) + '\', \'' + encodeOnclick(aTools[i]) + '\', \'\', \'\', \'' + encodeOnclick(target) + '\');" title="' + encodeOnclick(bTools[i]) + '"></a>';
+               }
+               
+               // As defined in the ref, we detect the type of each category to put an icon
+               switch(category) {
+                       case 'account':
+                       case 'auth':
+                       case 'automation':
+                       case 'client':
+                       case 'collaboration':
+                       case 'component':
+                       case 'conference':
+                       case 'directory':
+                       case 'gateway':
+                       case 'headline':
+                       case 'hierarchy':
+                       case 'proxy':
+                       case 'pubsub':
+                       case 'server':
+                       case 'store':
+                               break;
+                       
+                       default:
+                               category = 'others';
+               }
+               
+               // We display the item we found
+               $(pathID + ' .disco-' + category + ' .disco-category-title').after(
+                       '<div class="oneresult ' + target + '-oneresult ' + hash + '">' + 
+                               '<div class="one-icon ' + category + ' talk-images"></div>' + 
+                               '<div class="one-host">' + from + '</div>' + 
+                               '<div class="one-type">' + gName + '</div>' + 
+                               '<div class="one-actions">' + tools + '</div>' + 
+                       '</div>'
+               );
+               
+               // We display the category
+               $(pathID + ' .disco-' + category).show();
+       }
+       
+       else {
+               $(pathID + ' .disco-others .disco-category-title').after(
+                       '<div class="oneresult ' + target + '-oneresult">' + 
+                               '<div class="one-icon down talk-images"></div>' + 
+                               '<div class="one-host">' + from + '</div>' + 
+                               '<div class="one-type">' + _e("Service offline or broken") + '</div>' + 
+                       '</div>'
+               );
+               
+               // We display the category
+               $(pathID + ' .disco-others').show();
+       }
+       
+       // We hide the waiting stuffs if there's no remaining loading items
+       if(!$(pathID + ' .disco-wait .' + target + '-oneresult').size())
+               $(pathID + ' .disco-wait, #' + target + ' .wait').hide();
+}
+
+// Cleans the current data-form popup
+function cleanDataForm(target) {
+       if(target == 'discovery')
+               cleanDiscovery();
+       else
+               $('#' + target + ' div.results').empty();
+}
+
+// Displays the no result indicator
+function noResultDataForm(path) {
+       $(path).prepend('<p class="no-results">' + _e("Sorry, but the entity didn't return any result!") + '</p>');
+}
diff --git a/jappixmini/jappix/js/datastore.js b/jappixmini/jappix/js/datastore.js
new file mode 100644 (file)
index 0000000..b818b30
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+
+Jappix - An open social platform
+These are the temporary/persistent data store functions
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/06/11
+
+*/
+
+// Temporary: returns whether it is available or not
+function hasDB() {
+       if(window.sessionStorage)
+               return true;
+       
+       return false;
+}
+
+// Temporary: used to read a database entry
+function getDB(type, id) {
+       try {
+               return sessionStorage.getItem(type + '_' + id);
+       }
+       
+       catch(e) {
+               logThis('Error while getting a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1);
+               
+               return null;
+       }
+}
+
+// Temporary: used to update a database entry
+function setDB(type, id, value) {
+       try {
+               sessionStorage.setItem(type + '_' + id, value);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while writing a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1);
+               
+               return false;
+       }
+}
+
+// Temporary: used to remove a database entry
+function removeDB(type, id) {
+       try {
+               sessionStorage.removeItem(type + '_' + id);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while removing a temporary database entry (' + type + ' -> ' + id + '): ' + e, 1);
+               
+               return false;
+       }
+}
+
+// Temporary: used to check a database entry exists
+function existDB(type, id) {
+       var read = getDB(type, id);
+       
+       if(read != null)
+               return true;
+       
+       return false;
+}
+
+// Temporary: used to clear all the database
+function resetDB() {
+       try {
+               sessionStorage.clear();
+               
+               logThis('Temporary database cleared.', 3);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while clearing temporary database: ' + e, 1);
+               
+               return false;
+       }
+}
+
+// Persistent: returns whether it is available or not
+function hasPersistent() {
+       if(window.localStorage)
+               return true;
+       
+       return false;
+}
+
+// Persistent: used to read a database entry
+function getPersistent(type, id) {
+       try {
+               return localStorage.getItem(type + '_' + id);
+       }
+       
+       catch(e) {
+               logThis('Error while getting a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1);
+               
+               return null;
+       }
+}
+
+// Persistent: used to update a database entry
+function setPersistent(type, id, value) {
+       try {
+               localStorage.setItem(type + '_' + id, value);
+               
+               return true;
+       }
+       
+       // Database might be full
+       catch(e) {
+               logThis('Retrying: could not write a persistent database entry (' + type + ' -> ' + id + '): ' + e, 2);
+               
+               // Flush it!
+               flushPersistent();
+               
+               // Set the item again
+               try {
+                       localStorage.setItem(type + '_' + id, value);
+                       
+                       return true;
+               }
+               
+               // New error!
+               catch(e) {
+                       logThis('Aborted: error while writing a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1);
+                       
+                       return false;
+               }
+       }
+}
+
+// Persistent: used to remove a database entry
+function removePersistent(type, id) {
+       try {
+               localStorage.removeItem(type + '_' + id);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while removing a persistent database entry (' + type + ' -> ' + id + '): ' + e, 1);
+               
+               return false;
+       }
+}
+
+// Persistent: used to check a database entry exists
+function existPersistent(type, id) {
+       var read = getPersistent(type, id);
+       
+       if(read != null)
+               return true;
+       
+       return false;
+}
+
+// Persistent: used to clear all the database
+function resetPersistent() {
+       try {
+               localStorage.clear();
+               
+               logThis('Persistent database cleared.', 3);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while clearing persistent database: ' + e, 1);
+               
+               return false;
+       }
+}
+
+// Persistent: used to flush the database
+function flushPersistent() {
+       try {
+               // Get the stored session entry
+               var session = getPersistent('session', 1);
+               
+               // Clear the persistent database
+               localStorage.clear();
+               
+               // Restaure the stored session entry
+               if(session)
+                       setPersistent('session', 1, session);
+               
+               logThis('Persistent database flushed.', 3);
+               
+               return true;
+       }
+       
+       catch(e) {
+               logThis('Error while flushing persistent database: ' + e, 1);
+               
+               return false;
+       }
+}
diff --git a/jappixmini/jappix/js/date.js b/jappixmini/jappix/js/date.js
new file mode 100644 (file)
index 0000000..86731aa
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+
+Jappix - An open social platform
+These are the date related JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 17/08/11
+
+*/
+
+// Gets a stamp from a date
+function extractStamp(date) {
+       return Math.round(date.getTime() / 1000);
+}
+
+// Gets the time from a date
+function extractTime(date) {
+       return date.toLocaleTimeString();
+}
+
+// Gets the actual date stamp
+function getTimeStamp() {
+       return extractStamp(new Date());
+}
+
+// Gets the last user activity in seconds
+var LAST_ACTIVITY = 0;
+
+function getLastActivity() {
+       // Last activity not yet initialized?
+       if(LAST_ACTIVITY == 0)
+               return 0;
+       
+       return getTimeStamp() - LAST_ACTIVITY;
+}
+
+// Gets the last user available presence in seconds
+var PRESENCE_LAST_ACTIVITY = 0;
+
+function getPresenceLast() {
+       // Last presence stamp not yet initialized?
+       if(PRESENCE_LAST_ACTIVITY == 0)
+               return 0;
+       
+       return getTimeStamp() - PRESENCE_LAST_ACTIVITY;
+}
+
+// Generates the time for XMPP
+function getXMPPTime(location) {
+       /* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
+       
+       // Initialize
+       var jInit = new Date();
+       var year, month, day, hours, minutes, seconds;
+       
+       // Gets the UTC date
+       if(location == 'utc') {
+               year = jInit.getUTCFullYear();
+               month = jInit.getUTCMonth();
+               day = jInit.getUTCDate();
+               hours = jInit.getUTCHours();
+               minutes = jInit.getUTCMinutes();
+               seconds = jInit.getUTCSeconds();
+       }
+       
+       // Gets the local date
+       else {
+               year = jInit.getFullYear();
+               month = jInit.getMonth();
+               day = jInit.getDate();
+               hours = jInit.getHours();
+               minutes = jInit.getMinutes();
+               seconds = jInit.getSeconds();
+       }
+       
+       // Generates the date string
+       var jDate = year + '-';
+       jDate += padZero(month + 1) + '-';
+       jDate += padZero(day) + 'T';
+       jDate += padZero(hours) + ':';
+       jDate += padZero(minutes) + ':';
+       jDate += padZero(seconds) + 'Z';
+       
+       // Returns the date string
+       return jDate;
+}
+
+// Generates then human time
+function getCompleteTime() {
+       var init = new Date();
+       var time = padZero(init.getHours()) + ':';
+       time += padZero(init.getMinutes()) + ':';
+       time += padZero(init.getSeconds());
+       
+       return time;
+}
+
+// Gets the TZO of a date
+function getDateTZO() {
+       // Get the date
+       var date = new Date();
+       var offset = date.getTimezoneOffset();
+       
+       // Default vars
+       var sign = '';
+       var hours = 0;
+       var minutes = 0;
+       
+       // Process a neutral offset
+       if(offset < 0) {
+               offset = offset * -1;
+               sign = '+';
+       }
+       
+       // Get the values
+       var n_date = new Date(offset * 60 * 1000);
+       hours = n_date.getHours() - 1;
+       minutes = n_date.getMinutes();
+       
+       // Process the TZO
+       tzo = sign + padZero(hours) + ':' + padZero(minutes);
+       
+       // Return the processed value
+       return tzo;
+}
+
+// Parses a XMPP date (yyyy-mm-dd, hh-mm-ss) into an human-readable one
+function parseDate(to_parse) {
+       var date = Date.jab2date(to_parse);
+       var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')';
+       
+       return parsed; 
+}
+
+// Parses a XMPP date (yyyy-mm-dd) into an human-readable one
+function parseDay(to_parse) {
+       var date = Date.jab2date(to_parse);
+       var parsed = date.toLocaleDateString();
+       
+       return parsed; 
+}
+
+// Parses a XMPP date (hh-mm-ss) into an human-readable one
+function parseTime(to_parse) {
+       var date = Date.jab2date(to_parse);
+       var parsed = date.toLocaleTimeString();
+       
+       return parsed; 
+}
+
+// Parses a XMPP date stamp into a relative one
+function relativeDate(to_parse) {
+       // Get the current date
+       var current_date = Date.jab2date(getXMPPTime('utc'));
+       var current_day = current_date.getDate();
+       var current_stamp = current_date.getTime();
+       
+       // Parse the given date
+       var old_date = Date.jab2date(to_parse);
+       var old_day = old_date.getDate();
+       var old_stamp = old_date.getTime();
+       var old_time = old_date.toLocaleTimeString();
+       
+       // Get the day number between the two dates
+       var days = Math.round((current_stamp - old_stamp) / 86400000);
+       
+       // Invalid date?
+       if(isNaN(old_stamp) || isNaN(days))
+               return getCompleteTime();
+       
+       // Is it today?
+       if(current_day == old_day)
+               return old_time;
+       
+       // It is yesterday?
+       if(days <= 1)
+               return _e("Yesterday") + ' - ' + old_time;
+       
+       // Is it less than a week ago?
+       if(days <= 7)
+               return printf(_e("%s days ago"), days) + ' - ' + old_time;
+       
+       // Another longer period
+       return old_date.toLocaleDateString() + ' - ' + old_time;
+}
+
+// Reads a message delay
+function readMessageDelay(node) {
+       // Initialize
+       var delay, d_delay;
+       
+       // Read the delay
+       d_delay = jQuery(node).find('delay[xmlns=' + NS_URN_DELAY + ']:first').attr('stamp');
+       
+       // New delay (valid XEP)
+       if(d_delay)
+               delay = d_delay;
+       
+       // Old delay (obsolete XEP!)
+       else {
+               // Try to read the old-school delay
+               var x_delay = jQuery(node).find('x[xmlns=' + NS_DELAY + ']:first').attr('stamp');
+               
+               if(x_delay)
+                       delay = x_delay.replace(/^(\w{4})(\w{2})(\w{2})T(\w{2}):(\w{2}):(\w{2})Z?(\S+)?/, '$1-$2-$3T$4:$5:$6Z$7');
+       }
+       
+       return delay;
+}
diff --git a/jappixmini/jappix/js/directory.js b/jappixmini/jappix/js/directory.js
new file mode 100644 (file)
index 0000000..ebe1a57
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+
+Jappix - An open social platform
+These are the directory JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/03/11
+
+*/
+
+// Opens the directory popup
+function openDirectory() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("User directory") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="directory-head">' + 
+                       '<div class="directory-server-text">' + _e("Server to query") + '</div>' + 
+                       
+                       '<input name="directory-server-input" class="directory-server-input" value="' + encodeQuotes(HOST_VJUD) + '" />' + 
+               '</div>' + 
+               
+               '<div class="results directory-results"></div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('directory', html);
+       
+       // Associate the events
+       launchDirectory();
+       
+       // Start a search!
+       startDirectory();
+       
+       return false;
+}
+
+// Quits the directory popup
+function closeDirectory() {
+       // Destroy the popup
+       destroyPopup('directory');
+       
+       return false;
+}
+
+// Launches a directory search
+function startDirectory() {
+       // Get the server to query
+       var server = $('#directory .directory-server-input').val();
+       
+       // Launch the search!
+       dataForm($('#directory .directory-server-input').val(), 'search', '', '', 'directory');
+       
+       logThis('Directory search launched: ' + server);
+       
+       return false;
+}
+
+// Plugin launcher
+function launchDirectory() {
+       // Click event
+       $('#directory .bottom .finish').click(closeDirectory);
+       
+       // Keyboard event
+       $('#directory .directory-server-input').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // No value?
+                       if(!$(this).val())
+                               $(this).val(HOST_VJUD);
+                       
+                       // Start the directory search
+                       startDirectory();
+                       
+                       return false;
+               }
+       });
+}
diff --git a/jappixmini/jappix/js/discovery.js b/jappixmini/jappix/js/discovery.js
new file mode 100644 (file)
index 0000000..867037b
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+
+Jappix - An open social platform
+These are the discovery JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/03/11
+
+*/
+
+// Opens the discovery popup
+function openDiscovery() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Service discovery") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="discovery-head">' + 
+                       '<div class="disco-server-text">' + _e("Server to query") + '</div>' + 
+                       
+                       '<input name="disco-server-input" class="disco-server-input" value="' + encodeQuotes(HOST_MAIN) + '" />' + 
+               '</div>' + 
+               
+               '<div class="results discovery-results">' + 
+                       '<div class="disco-category disco-account">' + 
+                               '<p class="disco-category-title">' + _e("Accounts") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-auth">' + 
+                               '<p class="disco-category-title">' + _e("Authentications") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-automation">' + 
+                               '<p class="disco-category-title">' + _e("Automation") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-client">' + 
+                               '<p class="disco-category-title">' + _e("Clients") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-collaboration">' + 
+                               '<p class="disco-category-title">' + _e("Collaboration") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-component">' + 
+                               '<p class="disco-category-title">' + _e("Components") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-conference">' + 
+                               '<p class="disco-category-title">' + _e("Rooms") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-directory">' + 
+                               '<p class="disco-category-title">' + _e("Directories") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-gateway">' + 
+                               '<p class="disco-category-title">' + _e("Gateways") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-headline">' + 
+                               '<p class="disco-category-title">' + _e("News") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-hierarchy">' + 
+                               '<p class="disco-category-title">' + _e("Hierarchy") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-proxy">' + 
+                               '<p class="disco-category-title">' + _e("Proxies") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-pubsub">' + 
+                               '<p class="disco-category-title">' + _e("Publication/Subscription") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-server">' + 
+                               '<p class="disco-category-title">' + _e("Server") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-store">' + 
+                               '<p class="disco-category-title">' + _e("Storage") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-others">' + 
+                               '<p class="disco-category-title">' + _e("Others") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="disco-category disco-wait">' + 
+                               '<p class="disco-category-title">' + _e("Loading") + '</p>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('discovery', html);
+       
+       // Associate the events
+       launchDiscovery();
+       
+       // We request a disco to the default server
+       startDiscovery();
+       
+       return false;
+}
+
+// Quits the discovery popup
+function closeDiscovery() {
+       // Destroy the popup
+       destroyPopup('discovery');
+       
+       return false;
+}
+
+// Launches a discovery
+function startDiscovery() {
+       /* REF: http://xmpp.org/extensions/xep-0030.html */
+       
+       // We get the server to query
+       var discoServer = $('#discovery .disco-server-input').val();
+       
+       // We launch the items query
+       dataForm(discoServer, 'browse', '', '', 'discovery');
+       
+       logThis('Service discovery launched: ' + discoServer);
+       
+       return false;
+}
+
+// Cleans the discovery results
+function cleanDiscovery() {
+       // We remove the results
+       $('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove();
+       
+       // We clean the user info
+       $('#discovery .disco-server-info').text('');
+       
+       // We hide the wait icon, the no result alert and the results
+       $('#discovery .wait, #discovery .disco-category').hide();
+}
+
+// Plugin launcher
+function launchDiscovery() {
+       // Click event
+       $('#discovery .bottom .finish').click(closeDiscovery);
+       
+       // Keyboard event
+       $('#discovery .disco-server-input').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // No value?
+                       if(!$(this).val())
+                               $(this).val(HOST_MAIN);
+                       
+                       // Start the discovery
+                       startDiscovery();
+                       
+                       return false;
+               }
+       });
+}
diff --git a/jappixmini/jappix/js/error.js b/jappixmini/jappix/js/error.js
new file mode 100644 (file)
index 0000000..c16ca2a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+
+Jappix - An open social platform
+These are the error functions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 02/04/11
+
+*/
+
+// Shows the given error output
+function showError(condition, reason, type) {
+       // Enough data to output the error
+       if(condition || reason) {
+               // Initialize the error text
+               var eText = '';
+               
+               // Any error condition
+               if(condition)
+                       eText += condition;
+               
+               // Any error type
+               if(type && eText)
+                       eText += ' (' + type + ')';
+               
+               // Any error reason
+               if(reason) {
+                       if(eText)
+                               eText += ' - ';
+                       
+                       eText += reason;
+               }
+               
+               // We reveal the error
+               openThisError(1);
+               
+               // Create the error text
+               $('#board .one-board.error[data-id=1] span').text(eText);
+       }
+       
+       // Not enough data to output the error: output a generic board
+       else
+               openThisError(2);
+}
+
+// Handles the error from a packet and return true if any error
+function handleError(packet) {
+       /* REF: http://xmpp.org/extensions/xep-0086.html */
+       
+       // Initialize
+       var type, code, reason, condition;
+       var node = $(packet);
+       
+       // First level error (connection error)
+       if(node.is('error')) {
+               // Get the value
+               code = node.attr('code');
+               
+               // Specific error reason
+               switch(code) {
+                       case '401':
+                               reason = _e("Authorization failed");
+                               break;
+                       
+                       case '409':
+                               reason = _e("Registration failed, please choose a different username");
+                               break;
+                       
+                       case '503':
+                               reason = _e("Service unavailable");
+                               break;
+                       
+                       case '500':
+                               reason = _e("Internal server error, try later");
+                               break;
+                       
+                       default:
+                               reason = node.find('text').text();
+                               break;
+               }
+               
+               // Remove the general wait item (security)
+               removeGeneralWait();
+               
+               // Show reconnect pane
+               if(CURRENT_SESSION && CONNECTED) {
+                       // Anonymous?
+                       if(isAnonymous())
+                               createReconnect('anonymous');
+                       else
+                               createReconnect('normal');
+               }
+               
+               // Show the homepage (security)
+               else if(!CURRENT_SESSION || !CONNECTED) {
+                       $('#home').show();
+                       pageTitle('home');
+               }
+               
+               // Still connected? (security)
+               if(isConnected())
+                       con.disconnect();
+               
+               logThis('First level error received.', 1);
+       }
+       
+       // Second level error (another error)
+       else if(node.find('error').size()) {
+               type = node.find('error').attr('type');
+               reason = node.find('error text').text();
+               condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' ');
+               
+               logThis('Second level error received.', 1);
+       }
+       
+       // No error
+       else
+               return false;
+       
+       // Show the error board
+       showError(condition, reason, type);
+       
+       // Return there's an error
+       return true;
+}
+
+// Handles the error reply of a packet
+function handleErrorReply(packet) {
+       return handleError(packet.getNode());
+}
+
+// Handles the error reply for a message
+function handleMessageError(packet) {
+       if(!handleErrorReply(packet))
+               handleMessage(packet);
+}
diff --git a/jappixmini/jappix/js/favorites.js b/jappixmini/jappix/js/favorites.js
new file mode 100644 (file)
index 0000000..69a042e
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+
+Jappix - An open social platform
+These are the favorites JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/06/11
+
+*/
+
+// Opens the favorites popup
+function openFavorites() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Manage favorite rooms") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="switch-fav">' + 
+                       '<div class="room-switcher room-list">' + 
+                               '<div class="icon list-icon talk-images"></div>' + 
+                               
+                               _e("Change favorites") + 
+                       '</div>' + 
+                       
+                       '<div class="room-switcher room-search">' + 
+                               '<div class="icon search-icon talk-images"></div>' + 
+                               
+                               _e("Search a room") + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div class="static-fav">' + 
+                       '<div class="favorites-edit favorites-content">' + 
+                               '<div class="head fedit-head static-fav-head">' + 
+                                       '<div class="head-text fedit-head-text">' + _e("Select a favorite") + '</div>' + 
+                                       
+                                       '<select name="fedit-head-select" class="head-select fedit-head-select"></select>' + 
+                               '</div>' + 
+                               
+                               '<div class="results fedit-results static-fav-results">' + 
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Name") + '</label>' + 
+                                               
+                                               '<input class="fedit-title" type="text" required="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Nickname") + '</label>' + 
+                                               
+                                               '<input class="fedit-nick" type="text" value="' + getNick() + '" required="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Room") + '</label>' + 
+                                               
+                                               '<input class="fedit-chan" type="text" required="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Server") + '</label>' + 
+                                               
+                                               '<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Password") + '</label>' + 
+                                               
+                                               '<input class="fedit-password" type="password" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-line">' + 
+                                               '<label>' + _e("Automatic") + '</label>' + 
+                                               
+                                               '<input type="checkbox" class="fedit-autojoin" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="fedit-actions">' + 
+                                               '<a href="#" class="fedit-terminate fedit-add add one-button talk-images">' + _e("Add") + '</a>' + 
+                                               '<a href="#" class="fedit-terminate fedit-edit one-button talk-images">' + _e("Edit") + '</a>' + 
+                                               '<a href="#" class="fedit-terminate fedit-remove remove one-button talk-images">' + _e("Remove") + '</a>' + 
+                                       '</div>' + 
+                               '</div>' + 
+                       '</div>' + 
+                       
+                       '<div class="favorites-search favorites-content">' + 
+                               '<div class="head fsearch-head static-fav-head">' + 
+                                       '<div class="head-text fsearch-head-text">' + _e("Search a room on") + '</div>' + 
+                                       
+                                       '<input type="text" class="head-input fsearch-head-server" value="' + HOST_MUC + '" />' + 
+                               '</div>' + 
+                               
+                               '<div class="results fsearch-results static-fav-results">' + 
+                                       '<p class="fsearch-noresults">' + _e("No room found on this server.") + '</p>' + 
+                               '</div>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('favorites', html);
+       
+       // Load the favorites
+       loadFavorites();
+       
+       // Associate the events
+       launchFavorites();
+}
+
+// Resets the favorites elements
+function resetFavorites() {
+       var path = '#favorites ';
+       
+       $(path + '.wait, ' + path + '.fedit-terminate').hide();
+       $(path + '.fedit-add').show();
+       $(path + '.fsearch-oneresult').remove();
+       $(path + 'input').val('');
+       $(path + '.please-complete').removeClass('please-complete');
+       $(path + '.fedit-nick').val(getNick());
+       $(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC);
+       $(path + '.fedit-autojoin').attr('checked', false);
+}
+
+// Quits the favorites popup
+function quitFavorites() {
+       // Destroy the popup
+       destroyPopup('favorites');
+       
+       return false;
+}
+
+// Adds a room to the favorites
+function addThisFavorite(roomXID, roomName) {
+       // Button path
+       var button = '#favorites .fsearch-results div[data-xid=' + escape(roomXID) + '] a.one-button';
+       
+       // Add a remove button instead of the add one
+       $(button + '.add').replaceWith('<a href="#" class="one-button remove talk-images">' + _e("Remove") + '</a>');
+       
+       // Click event
+       $(button + '.remove').click(function() {
+               return removeThisFavorite(roomXID, roomName);
+       });
+       
+       // Hide the add button in the (opened?) groupchat
+       $('#' + hex_md5(roomXID) + ' .tools-add').hide();
+       
+       // Add the database entry
+       displayFavorites(roomXID, explodeThis(' (', roomName, 0), getNick(), '0', '');
+       
+       // Publish the favorites
+       favoritePublish();
+       
+       return false;
+}
+
+// Removes a room from the favorites
+function removeThisFavorite(roomXID, roomName) {
+       // Button path
+       var button = '#favorites .fsearch-results div[data-xid=' + escape(roomXID) + '] a.one-button';
+       
+       // Add a remove button instead of the add one
+       $(button + '.remove').replaceWith('<a href="#" class="one-button add talk-images">' + _e("Add") + '</a>');
+       
+       // Click event
+       $(button + '.add').click(function() {
+               return addThisFavorite(roomXID, roomName);
+       });
+       
+       // Show the add button in the (opened?) groupchat
+       $('#' + hex_md5(roomXID) + ' .tools-add').show();
+       
+       // Remove the favorite
+       removeFavorite(roomXID, true);
+       
+       // Publish the favorites
+       favoritePublish();
+       
+       return false;
+}
+
+// Edits a favorite
+function editFavorite() {
+       // Path to favorites
+       var favorites = '#favorites .';
+       
+       // Reset the favorites
+       resetFavorites();
+       
+       // Show the edit/remove button, hide the others
+       $(favorites + 'fedit-terminate').hide();
+       $(favorites + 'fedit-edit').show();
+       $(favorites + 'fedit-remove').show();
+       
+       // We retrieve the values
+       var xid = $(favorites + 'fedit-head-select').val();
+       var data = XMLFromString(getDB('favorites', xid));
+       
+       // If this is not the default room
+       if(xid != 'none') {
+               // We apply the values
+               $(favorites + 'fedit-title').val($(data).find('name').text());
+               $(favorites + 'fedit-nick').val($(data).find('nick').text());
+               $(favorites + 'fedit-chan').val(getXIDNick(xid));
+               $(favorites + 'fedit-server').val(getXIDHost(xid));
+               $(favorites + 'fedit-password').val($(data).find('password').text());
+               
+               if($(data).find('autojoin').text() == '1')
+                       $(favorites + 'fedit-autojoin').attr('checked', true);
+       }
+       
+       else
+               resetFavorites();
+}
+
+// Adds a favorite
+function addFavorite() {
+       // Path to favorites
+       var favorites = '#favorites .';
+       
+       // We reset the inputs
+       $(favorites + 'fedit-title, ' + favorites + 'fedit-nick, ' + favorites + 'fedit-chan, ' + favorites + 'fedit-server, ' + favorites + 'fedit-password').val('');
+       
+       // Show the add button, hide the others
+       $(favorites + 'fedit-terminate').hide();
+       $(favorites + 'fedit-add').show();
+}
+
+// Terminate a favorite editing
+function terminateThisFavorite(type) {
+       // Path to favorites
+       var favorites = '#favorites ';
+       
+       // We get the values of the current edited groupchat
+       var old_xid = $(favorites + '.fedit-head-select').val();
+       
+       var title = $(favorites + '.fedit-title').val();
+       var nick = $(favorites + '.fedit-nick').val();
+       var room = $(favorites + '.fedit-chan').val();
+       var server = $(favorites + '.fedit-server').val();
+       var xid = room + '@' + server;
+       var password = $(favorites + '.fedit-password').val();
+       var autojoin = '0';
+       
+       if($(favorites + '.fedit-autojoin').filter(':checked').size())
+               autojoin = '1';
+       
+       // We check the missing values and send this if okay
+       if((type == 'add') || (type == 'edit')) {
+               if(title && nick && room && server) {
+                       // Remove the edited room
+                       if(type == 'edit')
+                               removeFavorite(old_xid, true);
+                       
+                       // Display the favorites
+                       displayFavorites(xid, title, nick, autojoin, password);
+                       
+                       // Reset the inputs
+                       resetFavorites();
+               }
+               
+               else {
+                       $(favorites + 'input[required]').each(function() {
+                               var select = $(this);
+                               
+                               if(!select.val())
+                                       $(document).oneTime(10, function() {
+                                               select.addClass('please-complete').focus();
+                                       });
+                               else
+                                       select.removeClass('please-complete');  
+                       });
+               }
+       }
+       
+       // Must remove a favorite?
+       else if(type == 'remove') {
+               removeFavorite(old_xid, true);
+               
+               // Reset the inputs
+               resetFavorites();
+       }
+       
+       // Publish the new favorites
+       favoritePublish();
+       
+       logThis('Action on this bookmark: ' + room + '@' + server + ' / ' + type, 3);
+       
+       return false;
+}
+
+// Removes a favorite
+function removeFavorite(xid, database) {
+       // We remove the target favorite everywhere needed
+       $('.buddy-conf-groupchat-select option[value=' + xid + ']').remove();
+       $('.fedit-head-select option[value=' + xid + ']').remove();
+       
+       // Must remove it from database?
+       if(database)
+               removeDB('favorites', xid);
+}
+
+// Sends a favorite to the XMPP server
+function favoritePublish() {
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var query = iq.setQuery(NS_PRIVATE);
+       var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_BOOKMARKS}));
+       
+       // We generate the XML
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored favorite
+               if(explodeThis('_', current, 0) == 'favorites') {
+                       var data = XMLFromString(sessionStorage.getItem(current));
+                       var xid = $(data).find('xid').text();
+                       var rName = $(data).find('name').text();
+                       var nick = $(data).find('nick').text();
+                       var password = $(data).find('password').text();
+                       var autojoin = $(data).find('autojoin').text();
+                       
+                       // We create the node for this groupchat
+                       var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS}));
+                       item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick));
+                       
+                       if(password)
+                               item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password));
+                       
+                       logThis('Bookmark sent: ' + xid, 3);
+               }
+       }
+       
+       con.send(iq);
+}
+
+// Gets a list of the MUC items on a given server
+function getGCList() {
+       var path = '#favorites .';
+       var gcServer = $('.fsearch-head-server').val();
+       
+       // We reset some things
+       $(path + 'fsearch-oneresult').remove();
+       $(path + 'fsearch-noresults').hide();
+       $(path + 'wait').show();
+       
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setTo(gcServer);
+       
+       iq.setQuery(NS_DISCO_ITEMS);
+       
+       con.send(iq, handleGCList);
+}
+
+// Handles the MUC items list
+function handleGCList(iq) {
+       var path = '#favorites .';
+       var from = fullXID(getStanzaFrom(iq));
+       
+       if (!iq || (iq.getType() != 'result')) {
+               openThisError(3);
+               
+               $(path + 'wait').hide();
+               
+               logThis('Error while retrieving the rooms: ' + from, 1);
+       }
+       
+       else {
+               var handleXML = iq.getQuery();
+               
+               if($(handleXML).find('item').size()) {
+                       // Initialize the HTML code
+                       var html = '';
+                       
+                       $(handleXML).find('item').each(function() {
+                               var roomXID = $(this).attr('jid');
+                               var roomName = $(this).attr('name');
+                               
+                               if(roomXID && roomName) {
+                                       // Escaped values
+                                       var escaped_xid = encodeOnclick(roomXID);
+                                       var escaped_name = encodeOnclick(roomName);
+                                       
+                                       // Initialize the room HTML
+                                       html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(roomXID) + '">' + 
+                                                       '<div class="room-name">' + roomName.htmlEnc() + '</div>' + 
+                                                       '<a href="#" class="one-button join talk-images" onclick="return joinFavorite(\'' + escaped_xid + '\');">' + _e("Join") + '</a>';
+                                       
+                                       // This room is yet a favorite
+                                       if(existDB('favorites', roomXID))
+                                               html += '<a href="#" class="one-button remove talk-images" onclick="return removeThisFavorite(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + _e("Remove") + '</a>';
+                                       else
+                                               html += '<a href="#" class="one-button add talk-images" onclick="return addThisFavorite(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + _e("Add") + '</a>';
+                                       
+                                       // Close the room HTML
+                                       html += '</div>';
+                               }
+                       });
+                       
+                       // Append this code to the popup
+                       $(path + 'fsearch-results').append(html);
+               }
+               
+               else
+                       $(path + 'fsearch-noresults').show();
+               
+               logThis('Rooms retrieved: ' + from, 3);
+       }
+       
+       $(path + 'wait').hide();
+}
+
+// Joins a groupchat from favorites
+function joinFavorite(room) {
+       quitFavorites();
+       checkChatCreate(room, 'groupchat', '', '', getXIDNick(room));
+       
+       return false;
+}
+
+// Displays a given favorite
+function displayFavorites(xid, name, nick, autojoin, password) {
+       // Generate the HTML code
+       var html = '<option value="' + encodeQuotes(xid) + '">' + name.htmlEnc() + '</option>';
+       
+       // Remove the existing favorite
+       removeFavorite(xid, false);
+       
+       // We complete the select forms
+       $('#buddy-list .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html);
+       
+       // We store the informations
+       var value = '<groupchat><xid>' + xid.htmlEnc() + '</xid><name>' + name.htmlEnc() + '</name><nick>' + nick.htmlEnc() + '</nick><autojoin>' + autojoin.htmlEnc() + '</autojoin><password>' + password.htmlEnc() + '</password></groupchat>';
+       setDB('favorites', xid, value);
+}
+
+// Loads the favorites for the popup
+function loadFavorites() {
+       // Initialize the HTML code
+       var html = '';
+       
+       // Read the database
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored favorite
+               if(explodeThis('_', current, 0) == 'favorites') {
+                       var data = XMLFromString(sessionStorage.getItem(current));
+                       
+                       // Add the current favorite to the HTML code
+                       html += '<option value="' + encodeQuotes($(data).find('xid').text()) + '">' + $(data).find('name').text().htmlEnc() + '</option>';
+               }
+       }
+       
+       // Generate specific HTML code
+       var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' + _e("Select a favorite") +  '</option>' + html;
+       var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' + _e("Select a favorite") + '</option>' + html;
+       
+       // Append the HTML code
+       $('#buddy-list .buddy-conf-groupchat-select').html(favorites_bubble);
+       $('#favorites .fedit-head-select').html(favorites_popup);
+}
+
+// Plugin launcher
+function launchFavorites() {
+       var path = '#favorites .';
+       
+       // Keyboard events
+       $(path + 'fsearch-head-server').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // No value?
+                       if(!$(this).val())
+                               $(this).val(HOST_MUC);
+                       
+                       // Get the list
+                       getGCList();
+               }
+       });
+       
+       $(path + 'fedit-line input').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // Edit a favorite
+                       if($(path + 'fedit-edit').is(':visible'))
+                               terminateThisFavorite('edit');
+                       
+                       // Add a favorite
+                       else
+                               terminateThisFavorite('add');
+               }
+       });
+       
+       // Change events
+       $('.fedit-head-select').change(editFavorite);
+       
+       // Click events
+       $(path + 'room-switcher').click(function() {
+               $(path + 'favorites-content').hide();
+               resetFavorites();
+       });
+       
+       $(path + 'room-list').click(function() {
+               $(path + 'favorites-edit').show();
+       });
+       
+       $(path + 'room-search').click(function() {
+               $(path + 'favorites-search').show();
+               getGCList();
+       });
+       
+       $(path + 'fedit-add').click(function() {
+               return terminateThisFavorite('add');
+       });
+       
+       $(path + 'fedit-edit').click(function() {
+               return terminateThisFavorite('edit');
+       });
+       
+       $(path + 'fedit-remove').click(function() {
+               return terminateThisFavorite('remove');
+       });
+       
+       $(path + 'bottom .finish').click(function() {
+               return quitFavorites();
+       });
+}
diff --git a/jappixmini/jappix/js/features.js b/jappixmini/jappix/js/features.js
new file mode 100644 (file)
index 0000000..4944be0
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+
+Jappix - An open social platform
+This is the server features JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 01/06/11
+
+*/
+
+// Gets the features of a server
+function getFeatures() {
+       /* REF: http://xmpp.org/extensions/xep-0030.html */
+       
+       // Get the main values
+       var to = getServer();
+       var caps = con.server_caps;
+       var xml = null;
+       
+       // Try to get the stored data
+       if(caps)
+               xml = XMLFromString(getPersistent('caps', caps));
+       
+       // Any stored data?
+       if(xml) {
+               handleFeatures(xml);
+               
+               logThis('Read server CAPS from cache.');
+       }
+       
+       // Not stored (or no CAPS)!
+       else {
+               var iq = new JSJaCIQ();
+               
+               iq.setTo(to);
+               iq.setType('get');
+               iq.setQuery(NS_DISCO_INFO);
+               
+               con.send(iq, handleDiscoInfos);
+               
+               logThis('Read server CAPS from network.');
+       }
+}
+
+// Handles the features of a server
+function handleFeatures(xml) {
+       // Selector
+       var selector = $(xml);
+       
+       // Markers
+       var pep = false;
+       var pubsub = false;
+       var archive = false;
+       var archive_auto = false;
+       var archive_manual = false;
+       var archive_manage = false;
+       var archive_pref = false;
+       var commands = false;
+       
+       // Scan the features
+       if(selector.find('identity[category=pubsub][type=pep]').size())
+               pep = true;
+       if(selector.find('feature[var=' + NS_PUBSUB + ']').size())
+               pubsub = true;
+       if(selector.find('feature[var=' + NS_URN_ARCHIVE + ']').size())
+               archive = true;
+       if(selector.find('feature[var=' + NS_URN_AR_AUTO + ']').size())
+               archive_auto = true;
+       if(selector.find('feature[var=' + NS_URN_AR_MANUAL + ']').size())
+               archive_manual = true;
+       if(selector.find('feature[var=' + NS_URN_AR_MANAGE + ']').size())
+               archive_manage = true;
+       if(selector.find('feature[var=' + NS_URN_AR_PREF + ']').size())
+               archive_pref = true;
+       if(selector.find('feature[var=' + NS_COMMANDS + ']').size())
+               commands = true;
+       
+       // Enable the pep elements if available
+       if(pep) {
+               // Update our database
+               enableFeature('pep');
+               
+               // Get the microblog
+               getInitMicroblog();
+               
+               // Get the notifications
+               getNotifications();
+               
+               // Geolocate the user
+               geolocate();
+               
+               // Enable microblogging send tools
+               waitMicroblog('sync');
+               $('.postit.attach').css('display', 'block');
+               
+               logThis('XMPP server supports PEP.', 3);
+       }
+       
+       // Disable microblogging send tools (no PEP!)
+       else {
+               waitMicroblog('unsync');
+               
+               logThis('XMPP server does not support PEP.', 2);
+       }
+       
+       // Enable the pubsub features if available
+       if(pubsub)
+               enableFeature(NS_PUBSUB);
+       
+       // Enable the archiving features if available
+       if(archive)
+               enableFeature(NS_URN_ARCHIVE);
+       
+       // Enable the archiving sub-features if available
+       if(archive_pref)
+               enableFeature(NS_URN_AR_PREF);
+       if(archive_auto)
+               enableFeature(NS_URN_AR_AUTO);
+       if(archive_manual)
+               enableFeature(NS_URN_AR_MANUAL);
+       if(archive_manage)
+               enableFeature(NS_URN_AR_MANAGE);
+       
+       // Enable the commands features if available
+       if(commands)
+               enableFeature(NS_COMMANDS);
+       
+       // Hide the private life fieldset if nothing to show
+       if(!pep && !archive_pref)
+               $('#options fieldset.privacy').hide();
+       
+       // Apply the features
+       applyFeatures('talk');
+       
+       // Process the buddy-list height
+       if(pep)
+               adaptRoster();
+       
+       return false;
+}
+
+// The function to apply the features to an element
+function applyFeatures(id) {
+       // Path to the elements
+       var path = '#' + id + ' .';
+       
+       // PEP features
+       if(enabledPEP())
+               $(path + 'pep-hidable').show();
+       
+       // PubSub features
+       if(enabledPubSub())
+               $(path + 'pubsub-hidable').show();
+       
+       // Archives features
+       if(enabledArchives() || enabledArchives('auto') || enabledArchives('manual') || enabledArchives('manage')) {
+               $(path + 'archives-hidable:not(.pref)').show();
+               
+               // Sub-feature: archives preferences
+               if(enabledArchives('pref'))
+                       $(path + 'archives-hidable.pref').show();
+       }
+       
+       // Commands features
+       if(enabledCommands())
+               $(path + 'commands-hidable').show();
+       
+       // XMPP links (browser feature)
+       if(navigator.registerProtocolHandler)
+               $(path + 'xmpplinks-hidable').show();
+}
+
+// Enables a feature
+function enableFeature(feature) {
+       setDB('feature', feature, 'true');
+}
+
+// Checks if a feature is enabled
+function enabledFeature(feature) {
+       if(getDB('feature', feature) == 'true')
+               return true;
+       else
+               return false;
+}
+
+// Returns the XMPP server PEP support
+function enabledPEP() {
+       return enabledFeature('pep');
+}
+
+// Returns the XMPP server PubSub support
+function enabledPubSub() {
+       return enabledFeature(NS_PUBSUB);
+}
+
+// Returns the XMPP server archives support
+function enabledArchives(sub) {
+       var xmlns = NS_URN_ARCHIVE;
+       
+       // Any sub element sent?
+       if(sub)
+               xmlns += ':' + sub;
+       
+       return enabledFeature(xmlns);
+}
+
+// Returns the XMPP server commands support
+function enabledCommands() {
+       return enabledFeature(NS_COMMANDS);
+}
diff --git a/jappixmini/jappix/js/filter.js b/jappixmini/jappix/js/filter.js
new file mode 100644 (file)
index 0000000..48e5238
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+
+Jappix - An open social platform
+These are the filtering JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Maranda
+Last revision: 04/08/11
+
+*/
+
+// Generates a given emoticon HTML code
+function emoteImage(image, text, after) {
+       return ' <img class="emoticon emoticon-' + image + ' smileys-images" alt="' + encodeQuotes(text) + '" src="' + './img/others/blank.gif' + '" /> ' + after;
+}
+
+// Filters a given message
+function filterThisMessage(neutralMessage, nick, html_encode) {
+       var filteredMessage = neutralMessage;
+       
+       // We encode the HTML special chars
+       if(html_encode)
+               filteredMessage = filteredMessage.htmlEnc();
+       
+       // /me command
+       filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7')
+       
+       // We replace the smilies text into images
+       .replace(/(:-?@)($|\s|<)/gi, emoteImage('angry', '$1', '$2'))
+       .replace(/(:-?\[)($|\s|<)/gi, emoteImage('bat', '$1', '$2'))
+       .replace(/(\(B\))($|\s|<)/g, emoteImage('beer', '$1', '$2'))
+       .replace(/((:-?D)|(XD))($|\s|<)/gi, emoteImage('biggrin', '$1', '$4'))
+       .replace(/(:-?\$)($|\s|<)/gi, emoteImage('blush', '$1', '$2'))
+       .replace(/(\(Z\))($|\s|<)/g, emoteImage('boy', '$1', '$2'))
+       .replace(/(\(W\))($|\s|<)/g, emoteImage('brflower', '$1', '$2'))                        
+       .replace(/((&lt;\/3)|(\(U\)))($|\s|<)/g, emoteImage('brheart', '$1', '$4'))                     
+       .replace(/(\(C\))($|\s|<)/g, emoteImage('coffee', '$1', '$2'))                  
+       .replace(/((8-\))|(\(H\)))($|\s|<)/g, emoteImage('coolglasses', '$1', '$4'))
+       .replace(/(:'-?\()($|\s|<)/gi, emoteImage('cry', '$1', '$2'))
+       .replace(/(\(%\))($|\s|<)/g, emoteImage('cuffs', '$1', '$2'))
+       .replace(/(\]:-?&gt;)($|\s|<)/gi, emoteImage('devil', '$1', '$2'))                      
+       .replace(/(\(D\))($|\s|<)/g, emoteImage('drink', '$1', '$2'))
+       .replace(/(@}-&gt;--)($|\s|<)/gi, emoteImage('flower', '$1', '$2'))
+       .replace(/((:-?\/)|(:-?S))($|\s|<)/gi, emoteImage('frowning', '$1', '$4'))
+       .replace(/(\(X\))($|\s|<)/g, emoteImage('girl', '$1', '$2'))
+       .replace(/((&lt;3)|(\(L\)))($|\s|<)/g, emoteImage('heart', '$1', '$4'))
+       .replace(/(\(}\))($|\s|<)/g, emoteImage('hugleft', '$1', '$2'))                 
+       .replace(/(\({\))($|\s|<)/g, emoteImage('hugright', '$1', '$2'))
+       .replace(/(:-?{})($|\s|<)/gi, emoteImage('kiss', '$1', '$2'))
+       .replace(/(\(I\))($|\s|<)/g, emoteImage('lamp', '$1', '$2'))
+       .replace(/(:-?3)($|\s|<)/gi, emoteImage('lion', '$1', '$2'))
+       .replace(/(\(E\))($|\s|<)/g, emoteImage('mail', '$1', '$2'))
+       .replace(/(\(S\))($|\s|<)/g, emoteImage('moon', '$1', '$2'))
+       .replace(/(\(8\))($|\s|<)/g, emoteImage('music', '$1', '$2'))
+       .replace(/((=-?O)|(:-?O))($|\s|<)/gi, emoteImage('oh', '$1', '$4'))
+       .replace(/(\(T\))($|\s|<)/g, emoteImage('phone', '$1', '$2'))
+       .replace(/(\(P\))($|\s|<)/g, emoteImage('photo', '$1', '$2'))
+       .replace(/(:-?!)($|\s|<)/gi, emoteImage('puke', '$1', '$2'))
+       .replace(/(\(@\))($|\s|<)/g, emoteImage('pussy', '$1', '$2'))
+       .replace(/(\(R\))($|\s|<)/g, emoteImage('rainbow', '$1', '$2'))
+       .replace(/(:-?\))($|\s|<)/gi, emoteImage('smile', '$1', '$2'))
+       .replace(/(\(\*\))($|\s|<)/g, emoteImage('star', '$1', '$2'))
+       .replace(/(:-?\|)($|\s|<)/gi, emoteImage('stare', '$1', '$2'))
+       .replace(/(\(N\))($|\s|<)/g, emoteImage('thumbdown', '$1', '$2'))
+       .replace(/(\(Y\))($|\s|<)/g, emoteImage('thumbup', '$1', '$2'))
+       .replace(/(:-?P)($|\s|<)/gi, emoteImage('tongue', '$1', '$2'))
+       .replace(/(:-?\()($|\s|<)/gi, emoteImage('unhappy', '$1', '$2'))
+       .replace(/(;-?\))($|\s|<)/gi, emoteImage('wink', '$1', '$2'))
+       
+       // Text in bold
+       .replace(/(^|\s|>)((\*)([^<>'"]+)(\*))($|\s|<)/gi, '$1<b>$2</b>$6')
+       
+       // Italic text
+       .replace(/(^|\s|>)((\/)([^<>'"]+)(\/))($|\s|<)/gi, '$1<i>$2</i>$6')
+       
+       // Underlined text
+       .replace(/(^|\s|>)((_)([^<>'"]+)(_))($|\s|<)/gi, '$1<span style="text-decoration: underline;">$2</span>$6');
+       
+       // Add the links
+       if(html_encode)
+               filteredMessage = applyLinks(filteredMessage, 'desktop');
+       
+       // Filter integratebox links
+       filteredMessage = filterIntegrateBox(filteredMessage);
+       
+       return filteredMessage;
+}
+
+// Filters a xHTML message to be displayed in Jappix
+function filterThisXHTML(code) {
+       // Allowed elements array
+       var elements = new Array(
+                                'a',
+                                'abbr',
+                                'acronym',
+                                'address',
+                                'blockquote',
+                                'body',
+                                'br',
+                                'cite',
+                                'code',
+                                'dd',
+                                'dfn',
+                                'div',
+                                'dt',
+                                'em',
+                                'h1',
+                                'h2',
+                                'h3',
+                                'h4',
+                                'h5',
+                                'h6',
+                                'head',
+                                'html',
+                                'img',
+                                'kbd',
+                                'li',
+                                'ol',
+                                'p',
+                                'pre',
+                                'q',
+                                'samp',
+                                'span',
+                                'strong',
+                                'title',
+                                'ul',
+                                'var'
+                               );
+       
+       // Allowed attributes array
+       var attributes = new Array(
+                                  'accesskey',
+                                  'alt',
+                                  'charset',
+                                  'cite',
+                                  'class',
+                                  'height',
+                                  'href',
+                                  'hreflang',
+                                  'id',
+                                  'longdesc',
+                                  'profile',
+                                  'rel',
+                                  'rev',
+                                  'src',
+                                  'style',
+                                  'tabindex',
+                                  'title',
+                                  'type',
+                                  'uri',
+                                  'version',
+                                  'width',
+                                  'xml:lang',
+                                  'xmlns'
+                                 );
+       
+       // Remove forbidden elements
+       $(code).find('html body *').each(function() {
+               // This element is not authorized
+               if(!existArrayValue(elements, (this).nodeName.toLowerCase()))
+                       $(this).remove();
+       });
+       
+       // Remove forbidden attributes
+       $(code).find('html body *').each(function() {
+               // Put a pointer on this element (jQuery way & normal way)
+               var cSelector = $(this);
+               var cElement = (this);
+               
+               // Loop the attributes of the current element
+               $(cElement.attributes).each(function(index) {
+                       // Read the current attribute
+                       var cAttr = cElement.attributes[index];
+                       var cName = cAttr.name;
+                       var cVal = cAttr.value;
+                       
+                       // This attribute is not authorized, or contains JS code
+                       if(!existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/)))
+                               cSelector.removeAttr(cName);
+               });
+       });
+       
+       // Filter some other elements
+       $(code).find('a').attr('target', '_blank');
+       
+       return $(code).find('html body').html();
+}
diff --git a/jappixmini/jappix/js/groupchat.js b/jappixmini/jappix/js/groupchat.js
new file mode 100644 (file)
index 0000000..c8dd13b
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+
+Jappix - An open social platform
+These are the groupchat JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Maranda, Eric
+Last revision: 28/08/11
+
+*/
+
+// Displays the MUC admin elements
+function displayMucAdmin(affiliation, id, xid, statuscode) {
+       // We must be in the "login" mode
+       if(isAnonymous())
+               return;
+       
+       // We check if the user is a room owner or administrator to give him privileges
+       if(affiliation == 'owner' || affiliation == 'admin')
+               $('#' + id + ' .tools-mucadmin').show();
+       
+       // We check if the room hasn't been yet created
+       if(statuscode == 201)
+               openThisInfo(4);
+       
+       // We add the click event
+       $('#' + id + ' .tools-mucadmin').click(function() {
+               openMucAdmin(xid, affiliation);
+       });
+}
+
+// Initializes a connection with a MUC groupchat
+function getMUC(room, nickname, password) {
+       // Room hash
+       var hash = hex_md5(room);
+       
+       // Reset the elements
+       $('#' + hash + ' .muc-ask').remove();
+       $('#' + hash + ' .compose').show();
+       
+       // No nickname?
+       if(!nickname) {
+               // Get some values
+               if(!isAnonymous())
+                       nickname = getNick();
+               else
+                       nickname = ANONYMOUS_NICK;
+               
+               // If the nickname could not be retrieved, ask it
+               if(!nickname)
+                       generateMUCAsk('nickname', room, hash, nickname, password);
+       }
+       
+       // Got our nickname?
+       if(nickname) {
+               // Get our general presence
+               var show = getDB('presence-show', 1);
+               var status = getDB('options', 'presence-status');
+       
+               // Set my nick
+               $('#' + hash).attr('data-nick', escape(nickname));
+       
+               // Send the appropriate presence
+               sendPresence(room + '/' + nickname, '', show, status, '', true, password, handleMUC);
+       }
+       
+       return false;
+}
+
+// Handles the MUC main elements
+function handleMUC(presence) {
+       // We get the xml content
+       var xml = presence.getNode();
+       var from = fullXID(getStanzaFrom(presence));
+       var room = bareXID(from);
+       var nickname = thisResource(from);
+       var hash = hex_md5(room);
+       
+       // No ID: must fix M-Link bug
+       if(presence.getID() == null)
+               presence.setID(1);
+       
+       logThis('First MUC presence: ' + from, 3);
+       
+       // Catch the errors
+       if(!handleError(xml)) {
+               // Define some stuffs
+               var muc_user = $(xml).find('x[xmlns=' + NS_MUC_USER + ']');
+               var affiliation = muc_user.find('item').attr('affiliation');
+                var statuscode = parseInt(muc_user.find('status').attr('code'));
+               
+               // Handle my presence
+               handlePresence(presence);
+               
+               // Check if I am a room owner
+               displayMucAdmin(affiliation, hash, room, statuscode);
+               
+               // Tell the MUC we can notify the incoming presences
+               $(document).oneTime('15s', function() {
+                       $('#' + hash).attr('data-initial', 'true');
+               });
+               
+               // Enable the chatting input
+               $(document).oneTime(10, function() {
+                       $('#' + hash + ' .message-area').removeAttr('disabled').focus();
+               });
+       }
+       
+       // A password is required
+       else if($(xml).find('error[type=auth] not-authorized').size())
+               generateMUCAsk('password', room, hash, nickname);
+       
+       // There's a nickname conflict
+       else if($(xml).find('error[type=cancel] conflict').size())
+               generateMUCAsk('nickname', room, hash);
+}
+
+// Generates a correct MUC asker
+function generateMUCAsk(type, room, hash, nickname, password) {
+       // Generate the path to the elements
+       var path_to = '#' + hash + ' .muc-ask';
+       
+       // Define the label text
+       var label_text;
+       
+       switch(type) {
+               case 'nickname':
+                       label_text = _e("Nickname");
+                       break;
+               
+               case 'password':
+                       label_text = _e("Password");
+                       break;
+       }
+       
+       // Create the HTML markup
+       $('#' + hash + ' .compose').hide();
+       
+       $('#' + hash).append(
+               '<div class="muc-ask text">' + 
+                       '<label>' + label_text + '</label>' + 
+                       '<input class="focusable" type="text" />' + 
+               '</div>'
+       );
+       
+       // When a key is pressed in the input
+       $(path_to + ' input').keyup(function(e) {
+               var value_input = $(this).val();
+               
+               // Enter key pressed
+               if((e.keyCode == 13) && value_input) {
+                       if(type == 'nickname')
+                               nickname = value_input;
+                       else if(type == 'password')
+                               password = value_input;
+                       
+                       return getMUC(room, nickname, password);
+               }
+       });
+       
+       // Focus on the input
+       $(document).oneTime(10, function() {
+               $(path_to + ' input').focus();
+       });
+}
+
+// Creates a new groupchat
+function groupchatCreate(hash, room, chan, nickname, password) {
+       /* REF: http://xmpp.org/extensions/xep-0045.html */
+       
+       logThis('New groupchat: ' + room, 3);
+       
+       // Create the chat content
+       generateChat('groupchat', hash, room, chan);
+       
+       // Create the chat switcher
+       generateSwitch('groupchat', hash, room, chan);
+       
+       // The icons-hover functions
+       tooltipIcons(room, hash);
+       
+       // Click event on the add tool
+       $('#' + hash + ' .tools-add').click(function() {
+               // Hide the icon (to tell the user all is okay)
+               $(this).hide();
+               
+               // Add the groupchat to the user favorites
+               addThisFavorite(room, chan);
+       });
+       
+       // Must show the add button?
+       if(!existDB('favorites', room))
+               $('#' + hash + ' .tools-add').show();
+       
+       // The event handlers
+       var inputDetect = $('#' + hash + ' .message-area');
+       
+       // Focus event
+       inputDetect.focus(function() {
+               chanCleanNotify(hash);
+       })
+       
+       // Blur event
+       inputDetect.blur(function() {
+               resetAutocompletion(hash);
+       })
+       
+       // Lock to the input
+       inputDetect.keypress(function(e) {
+               // Enter key
+               if(e.keyCode == 13) {
+                       // Add a new line
+                       if(e.shiftKey)
+                               inputDetect.val(inputDetect.val() + '\n');
+                       
+                       // Send the message
+                       else {
+                               sendMessage(hash, 'groupchat');
+                               
+                               // Reset the composing database entry
+                               setDB('chatstate', room, 'off');
+                       }
+                       
+                       return false;
+               }
+               
+               // Tabulation key
+               else if(e.keyCode == 9) {
+                       createAutocompletion(hash);
+                       
+                       return false;
+               }
+               
+               // Reset the autocompleter
+               else
+                       resetAutocompletion(hash);
+       });
+       
+       // Chatstate events
+       eventsChatState(inputDetect, room, hash);
+       
+       // Get the current muc informations and content
+       getMUC(room, nickname, password);
+}
+
+// Joins the defined groupchats
+function joinConfGroupchats() {
+       // Nothing to join?
+       if(!GROUPCHATS_JOIN)
+               return;
+       
+       // Values array
+       var muc_arr = [GROUPCHATS_JOIN];
+       var new_arr = [];
+       
+       // Try to split it
+       if(GROUPCHATS_JOIN.indexOf(',') != -1)
+               muc_arr = GROUPCHATS_JOIN.split(',');
+       
+       for(i in muc_arr) {
+               // Get the current value
+               var muc_current = trim(muc_arr[i]);
+               
+               // No current value?
+               if(!muc_current)
+                       continue;
+               
+               // Filter the current value
+               muc_current = generateXID(muc_current, 'groupchat');
+               
+               // Add the current value
+               if(!existArrayValue(new_arr, muc_current))
+                       new_arr.push(muc_current);
+       }
+       
+       // Join the chats
+       if(new_arr.length) {
+               for(g in new_arr)
+                       checkChatCreate(new_arr[g], 'groupchat');
+       }
+}
diff --git a/jappixmini/jappix/js/home.js b/jappixmini/jappix/js/home.js
new file mode 100644 (file)
index 0000000..5322501
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+
+Jappix - An open social platform
+These are the homepage JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, LinkMauve
+Last revision: 15/01/12
+
+*/
+
+// Allows the user to switch the difference home page elements
+function switchHome(div) {
+       // Path to
+       var home = '#home .';
+       var right = home + 'right ';
+       var current = right + '.homediv.' + div;
+       
+       // We switch the div
+       $(right + '.homediv, ' + right + '.top').hide();
+       $(right + '.' + div).show();
+       
+       // We reset the homedivs
+       $(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove();
+       
+       // Get the HTML code to display
+       var disable_form = '';
+       var lock_host = '';
+       var code = '';
+       
+       // Apply the previous link
+       switch(div) {
+               case 'loginer':
+               case 'anonymouser':
+               case 'registerer':
+                       if(!exists(right + '.top.sub')) {
+                               // Append the HTML code for previous link
+                               $(right + '.top.default').after('<h1 class="top sub loginer anonymouser registerer">&laquo; <a href="#" class="previous">' + _e("Previous") + '</a></h1>');
+                               
+                               // Click event on previous link
+                               $(home + 'top.sub a.previous').click(function() {
+                                       return switchHome('default');
+                               });
+                       }
+               
+               break;
+       }
+       
+       // Apply the form
+       switch(div) {
+               // Login tool
+               case 'loginer':
+                       lock_host = disableInput(LOCK_HOST, 'on');
+                       code = '<p>' + printf(_e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '<a href="#" class="to-anonymous">' + _e("anonymous mode") + '</a>') + '</p>' + 
+                               
+                               '<form action="#" method="post">' + 
+                                       '<fieldset>' + 
+                                               '<legend>' + _e("Required") + '</legend>' + 
+                                               
+                                               '<label for="lnick">' + _e("Address") + '</label>' + 
+                                               '<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" />' + 
+                                               '<label for="lpassword">' + _e("Password") + '</label>' + 
+                                               '<input type="password" class="password" id="lpassword" required="" />' + 
+                                               '<label for="lremember">' + _e("Remember me") + '</label>' + 
+                                               '<input type="checkbox" class="remember" id="lremember" />' + 
+                                       '</fieldset>' + 
+                                       
+                                       '<a href="#" class="advanced home-images">' + _e("Advanced") + '</a>' + 
+                                       
+                                       '<fieldset class="advanced">' + 
+                                               '<legend>' + _e("Advanced") + '</legend>' + 
+                                               
+                                               '<label for="lresource">' + _e("Resource") + '</label>' + 
+                                               '<input type="text" class="resource" id="lresource" value="' + JAPPIX_RESOURCE + '" />' + 
+                                               '<label for="lpriority">' + _e("Priority") + '</label>' + 
+                                               '<select class="priority" id="lpriority">' + 
+                                                       '<option value="1">' + _e("Low") + '</option>' + 
+                                                       '<option value="10" selected="">' + _e("Medium") + '</option>' + 
+                                                       '<option value="100">' + _e("High") + '</option>' + 
+                                               '</select>' + 
+                                       '</fieldset>' + 
+                                       
+                                       '<input type="submit" value="' + _e("Here we go!") + '" />' + 
+                               '</form>';
+                       
+                       break;
+               
+               // Anonymous login tool
+               case 'anonymouser':
+                       disable_form = disableInput(ANONYMOUS, 'off');
+                       code = '<p>' + printf(_e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '<a href="#" class="to-home">' + _e("login page") + '</a>') + '</p>' + 
+                               
+                               '<form action="#" method="post">' + 
+                                       '<fieldset>' + 
+                                               '<legend>' + _e("Required") + '</legend>' + 
+                                               
+                                               '<label>' + _e("Room") + '</label>' + 
+                                               '<input type="text" class="room"' + disable_form + ' pattern="[^/]+" required="" />' + 
+                                               
+                                               '<label>' + _e("Nickname") + '</label>' + 
+                                               '<input type="text" class="nick"' + disable_form + ' required="" />' + 
+                                       '</fieldset>' + 
+                                       
+                                       '<input type="submit" value="' + _e("Here we go!") + '"' + disable_form + ' />' + 
+                               '</form>' + 
+                               
+                               '<div class="info report">' + 
+                                       _e("Share this link with your friends:") + ' <span></span>' + 
+                               '</div>';
+                       
+                       break;
+               
+               // Register tool
+               case 'registerer':
+                       disable_form = disableInput(REGISTRATION, 'off');
+                       
+                       if(!disable_form)
+                               lock_host = disableInput(LOCK_HOST, 'on');
+                       
+                       code = '<p>' + _e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '</p>' + 
+                               
+                               '<form action="#" method="post">' + 
+                                       '<fieldset>' + 
+                                               '<legend>' + _e("Required") + '</legend>' + 
+                                               
+                                               '<label for="rnick">' + _e("Address") + '</label>' + 
+                                               '<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" />' + 
+                                               '<label for="rpassword">' + _e("Password") + '</label>' + 
+                                               '<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" />' + 
+                                               '<label for="spassword">' + _e("Confirm") + '</label><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" />' + 
+                                       '</fieldset>' + 
+                                       
+                                       '<input type="submit" value="' + _e("Here we go!") + '" ' + disable_form + '/>' + 
+                               '</form>';
+                       
+                       break;
+       }
+       
+       // Form disabled?
+       if(disable_form)
+               code += '<div class="info fail">' + 
+                               _e("This tool has been disabled, you cannot use it!") + 
+                       '</div>';
+       
+       // Create this HTML code
+       if(code && !exists(current)) {
+               // Append it!
+               $(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>');
+               
+               // Create the attached events
+               switch(div) {
+                       // Login tool
+                       case 'loginer':
+                               $(current + ' a.to-anonymous').click(function() {
+                                       return switchHome('anonymouser');
+                               });
+                               
+                               $(current + ' a.advanced').click(showAdvanced);
+                               
+                               $(current + ' form').submit(loginForm);
+                               
+                               break;
+                       
+                       // Anonymous login tool
+                       case 'anonymouser':
+                               $(current + ' a.to-home').click(function() {
+                                       return switchHome('loginer');
+                               });
+                               
+                               $(current + ' form').submit(doAnonymous);
+                               
+                               // Keyup event on anonymous join's room input
+                               $(current + ' input.room').keyup(function() {
+                                       var value = $(this).val();
+                                       var report = current + ' .report';
+                                       var span = report + ' span';
+                                       
+                                       if(!value) {
+                                               $(report).hide();
+                                               $(span).text('');
+                                       }
+                                       
+                                       else {
+                                               $(report).show();
+                                               $(span).text(JAPPIX_LOCATION + '?r=' + value);
+                                       }
+                               });
+                               
+                               break;
+                       
+                       // Register tool
+                       case 'registerer':
+                               $(current + ' form').submit(registerForm);
+                               
+                               break;
+               }
+       }
+       
+       // We focus on the first input
+       $(document).oneTime(10, function() {
+               $(right + 'input:visible:first').focus();
+       });
+       
+       return false;
+}
+
+// Allows the user to display the advanced login options
+function showAdvanced() {
+       // Hide the link
+       $('#home a.advanced').hide();
+       
+       // Show the fieldset
+       $('#home fieldset.advanced').show();
+       
+       return false;
+}
+
+// Reads the login form values
+function loginForm() {
+       // We get the values
+       var lPath = '#home .loginer ';
+       var lServer = $(lPath + '.server').val();
+       var lNick = $(lPath + '.nick').val();
+       var lPass = $(lPath + '.password').val();
+       var lResource = $(lPath + '.resource').val();
+       var lPriority = $(lPath + '.priority').val();
+       var lRemember = $(lPath + '.remember').filter(':checked').size();
+       
+       // Enough values?
+       if(lServer && lNick && lPass && lResource && lPriority)
+               doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember);
+       
+       // Something is missing?
+       else {
+               $(lPath + 'input[type=text], ' + lPath + 'input[type=password]').each(function() {
+                       var select = $(this);
+                       
+                       if(!select.val())
+                               $(document).oneTime(10, function() {
+                                       select.addClass('please-complete').focus();
+                               });
+                       else
+                               select.removeClass('please-complete');  
+               });
+       }
+       
+       return false;
+}
+
+// Reads the register form values
+function registerForm() {
+       var rPath = '#home .registerer ';
+       
+       // Remove the success info
+       $(rPath + '.success').remove();
+       
+       // Get the values
+       var username = $(rPath + '.nick').val();
+       var domain = $(rPath + '.server').val();
+       var pass = $(rPath + '.password').val();
+       var spass = $(rPath + '.spassword').val();
+       
+       // Enough values?
+       if(domain && username && pass && spass && (pass == spass)) {
+               // We remove the not completed class to avoid problems
+               $('#home .registerer input').removeClass('please-complete');
+               
+               // Fire the register event!
+               doRegister(username, domain, pass);
+       }
+       
+       // Something is missing?
+       else {
+               $(rPath + 'input[type=text], ' + rPath + 'input[type=password]').each(function() {
+                       var select = $(this);
+                       
+                       if(!select.val() || (select.is('#spassword') && pass && (pass != spass)))
+                               $(document).oneTime(10, function() {
+                                       select.addClass('please-complete').focus();
+                               });
+                       else
+                               select.removeClass('please-complete');  
+               });
+       }
+       
+       return false;
+}
+
+// Plugin launcher
+function launchHome() {
+       // Define the vars
+       var home = '#home ';
+       var button = home + 'button';
+       var corp = home + '.corporation';
+       var locale = home + '.locale';
+       
+       // Removes the <noscript /> elements to lighten the DOM
+       $('noscript').remove();
+       
+       // Allows the user to switch the home page
+       $(button).click(function() {
+               // Login button
+               if($(this).is('.login'))
+                       return switchHome('loginer');
+               
+               // Register button
+               else
+                       return switchHome('registerer');
+       });
+       
+       // Allows the user to view the corporation infobox
+       $(corp).hover(function() {
+               $(corp).addClass('hovered');
+       }, function() {
+               $(corp).removeClass('hovered');
+       });
+       
+       // Allows the user to switch the language
+       $(locale).hover(function() {
+               // Initialize the HTML code
+               var keepget = $(locale).attr('data-keepget');
+               var html = '<div class="list">';
+               
+               // Generate each locale HTML code
+               for(i in LOCALES_AVAILABLE_ID)
+                       html += '<a href="./?l=' + LOCALES_AVAILABLE_ID[i] + keepget + '">' + LOCALES_AVAILABLE_NAMES[i].htmlEnc() + '</a>';
+               
+               html += '</div>';
+               
+               // Append the HTML code
+               $(locale).append(html);
+       }, function() {
+               $(locale + ' .list').remove();
+       });
+       
+       // Disables the browser HTTP-requests stopper
+       $(document).keydown(function(e) {
+               if((e.keyCode == 27) && !isDeveloper())
+                       return false;
+       });
+       
+       // Warns for an obsolete browser
+       if(isObsolete()) {
+               // Add the code
+               $(locale).after(
+                       '<div class="obsolete">' + 
+                               '<p>' + _e("Your browser is out of date!") + '</p>' + 
+                               
+                               '<a class="firefox browsers-images" title="' + printf(_e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' + 
+                               '<a class="chrome browsers-images" title="' + printf(_e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' + 
+                               '<a class="safari browsers-images" title="' + printf(_e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' + 
+                               '<a class="opera browsers-images" title="' + printf(_e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' + 
+                               '<a class="ie browsers-images" title="' + printf(_e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' + 
+                       '</div>'
+               );
+               
+               // Display it later
+               $(home + '.obsolete').oneTime('1s', function() {
+                       $(this).slideDown();
+               });
+               
+               logThis('Jappix does not support this browser!', 2);
+       }
+       
+       logThis('Welcome to Jappix! Happy coding in developer mode!');
+}
+
+// Launch this plugin!
+$(document).ready(launchHome);
diff --git a/jappixmini/jappix/js/httpauth.js b/jappixmini/jappix/js/httpauth.js
new file mode 100644 (file)
index 0000000..857de6d
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+
+Jappix - An open social platform
+These are the http-auth JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/11/10
+
+*/
+
+// Replies to a HTTP request
+function requestReply(value, xml) {
+       // We parse the xml content
+       var from = fullXID(getStanzaFrom(xml));
+       var confirm = $(xml.getNode()).find('confirm');
+       var xmlns = confirm.attr('xmlns');
+       var id = confirm.attr('id');
+       var method = confirm.attr('method');
+       var url = confirm.attr('url');
+       
+       // We generate the reply message
+       var aMsg = new JSJaCMessage();
+       aMsg.setTo(from);
+       
+       // If "no"
+       if(value == 'no') {
+               aMsg.setType('error');
+               aMsg.appendNode('error', {'code': '401', 'type': 'auth'});
+       }
+       
+       // We set the confirm node
+       aMsg.appendNode('confirm', {'xmlns': xmlns, 'url': url, 'id': id, 'method': method});
+       
+       // We send the message
+       con.send(aMsg, handleErrorReply);
+       
+       logThis('Replying HTTP auth request: ' + from, 3);
+}
diff --git a/jappixmini/jappix/js/inbox.js b/jappixmini/jappix/js/inbox.js
new file mode 100644 (file)
index 0000000..9f54cb9
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+
+Jappix - An open social platform
+These are the inbox JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 08/06/11
+
+*/
+
+// Opens the inbox popup
+function openInbox() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Your inbox") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="head inbox-head">' + 
+                       '<div class="head-text inbox-head-text">' + _e("Available actions") + '</div>' + 
+                       
+                       '<div class="head-actions inbox-head-actions">' + 
+                               '<a href="#" class="a-delete-messages">' + _e("Clean") + '</a>' + 
+                               '<a href="#" class="a-new-message">' + _e("New") + '</a>' + 
+                               '<a href="#" class="a-show-messages">' + _e("Received") + '</a>' + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div class="inbox-results">' + 
+                       '<p class="inbox-noresults">' + _e("Your inbox is empty.") + '</p>' + 
+                       
+                       '<div class="inbox"></div>' + 
+               '</div>' + 
+               
+               '<div class="inbox-new">' + 
+                       '<div class="inbox-new-to inbox-new-block search">' + 
+                               '<p class="inbox-new-text">' + _e("To") + '</p>' + 
+                               
+                               '<input name="inbox-new-to-input" class="inbox-new-input inbox-new-to-input" type="text" required="" />' + 
+                       '</div>' + 
+                       
+                       '<div class="inbox-new-topic inbox-new-block">' + 
+                               '<p class="inbox-new-text">' + _e("Subject") + '</p>' + 
+                               
+                               '<input name="inbox-new-subject-input" class="inbox-new-input inbox-new-subject-input" type="text" required="" />' + 
+                       '</div>' + 
+                       
+                       '<div class="inbox-new-body inbox-new-block">' + 
+                               '<p class="inbox-new-text">' + _e("Content") + '</p>' + 
+                               
+                               '<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' + 
+                       '</div>' + 
+                       
+                       '<form class="inbox-new-file inbox-new-block" action="./php/file-share.php" method="post" enctype="multipart/form-data">' + 
+                               '<p class="inbox-new-text">' + _e("File") + '</p>' + 
+                               
+                               generateFileShare() + 
+                       '</form>' + 
+                       
+                       '<div class="inbox-new-send inbox-new-block">' + 
+                               '<a href="#" class="send one-button talk-images">' + _e("Send message") + '</a>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('inbox', html);
+       
+       // Associate the events
+       launchInbox();
+       
+       // Load the messages
+       loadInbox();
+       
+       return false;
+}
+
+// Closes the inbox popup
+function closeInbox() {
+       // Destroy the popup
+       destroyPopup('inbox');
+       
+       return false;
+}
+
+// Opens the message compose tool
+function composeInboxMessage(xid) {
+       // Open things
+       openInbox();
+       newInboxMessage();
+       
+       // Apply XID
+       $('#inbox .inbox-new-to-input').val(xid);
+       
+       // Focus to the next item
+       $(document).oneTime(10, function() {
+               $('#inbox .inbox-new-subject-input').focus();
+       });
+       
+       return false;
+}
+
+// Stores the inbox
+function storeInbox() {
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       var query = iq.setQuery(NS_PRIVATE);
+       var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_INBOX}));
+       
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored message
+               if(explodeThis('_', current, 0) == 'inbox') {
+                       // Get the values
+                       var value = $(XMLFromString(sessionStorage.getItem(current)));
+                       
+                       // Create the storage node
+                       storage.appendChild(iq.buildNode('message', {
+                                                                    'id': value.find('id').text().revertHtmlEnc(),
+                                                                    'from': value.find('from').text().revertHtmlEnc(),
+                                                                    'subject': value.find('subject').text().revertHtmlEnc(),
+                                                                    'status': value.find('status').text().revertHtmlEnc(),
+                                                                    'date': value.find('date').text().revertHtmlEnc(),
+                                                                    'xmlns': NS_INBOX
+                                                                   },
+                                                                   
+                                                                   value.find('content').text().revertHtmlEnc()
+                                                       ));
+               }
+       }
+       
+       con.send(iq);
+}
+
+// Creates a new normal message
+function newInboxMessage() {
+       // Init
+       var mPath = '#inbox .';
+       
+       // Reset the previous buddy search
+       resetBuddySearch('#inbox .inbox-new-to');
+       
+       // We switch the divs
+       $(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide();
+       $(mPath + 'inbox-new, #inbox .a-show-messages').show();
+       
+       // We focus on the first input
+       $(document).oneTime(10, function() {
+               $(mPath + 'inbox-new-to-input').focus();
+       });
+       
+       // We reset some stuffs
+       cleanNewInboxMessage();
+       
+       return false;
+}
+
+// Cleans the inbox
+function cleanNewInboxMessage() {
+       // Init
+       var mPath = '#inbox .';
+       
+       // We reset the forms
+       $(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete');
+       $(mPath + 'inbox-new-file a').remove();
+       $(mPath + 'inbox-new-file input').show();
+       
+       // We close an eventual opened message
+       $(mPath + 'message-content').remove();
+       $(mPath + 'one-message').removeClass('message-reading');
+}
+
+// Sends a normal message
+function sendInboxMessage(to, subject, body) {
+       // We send the message
+       var mess = new JSJaCMessage();
+       
+       // Main attributes
+       mess.setTo(to);
+       mess.setSubject(subject);
+       mess.setType('normal');
+       
+       // Any file to attach?
+       var attached = '#inbox .inbox-new-file a.file';
+       
+       if(exists(attached))
+               body += '\n' + 
+                       '\n' + 
+                       $(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
+       
+       // Set body
+       mess.setBody(body);
+       
+       con.send(mess, handleErrorReply);
+}
+
+// Performs the normal message sender checks
+function checkInboxMessage() {
+       // We get some informations
+       var mPath = '#inbox ';
+       var to = $(mPath + '.inbox-new-to-input').val();
+       var body = $(mPath + '.inbox-new-textarea').val();
+       var subject = $(mPath + '.inbox-new-subject-input').val();
+       
+       if(to && body && subject) {
+               // New array of XID
+               var xid = new Array(to);
+               
+               // More than one XID
+               if(to.indexOf(',') != -1)
+                       xid = to.split(',');
+               
+               for(i in xid) {
+                       var current = xid[i];
+                       
+                       // No current value?
+                       if(!current || current.match(/^(\s+)$/))
+                               continue;
+                       
+                       // Edit the XID if needed
+                       current = current.replace(/ /g, '');
+                       current = generateXID(current, 'chat');
+                       
+                       // We send the message
+                       sendInboxMessage(current, subject, body);
+                       
+                       // We clean the inputs
+                       cleanNewInboxMessage();
+                       
+                       logThis('Inbox message sent: ' + current, 3);
+               }
+               
+               // Close the inbox
+               closeInbox();
+       }
+       
+       else {
+               $(mPath + 'input[type=text], ' + mPath + 'textarea').each(function() {
+                       var current = this;
+                       
+                       if(!$(current).val()) {
+                               $(document).oneTime(10, function() {
+                                       $(current).addClass('please-complete').focus();
+                               });
+                       }
+                       
+                       else
+                               $(current).removeClass('please-complete');      
+               });
+       }
+       
+       return false;
+}
+
+// Shows the inbox messages
+function showInboxMessages() {
+       // Init
+       var mPath = '#inbox .';
+       
+       // We switch the divs
+       $(mPath + 'inbox-new').hide();
+       $(mPath + 'inbox-results').show();
+       
+       // We show a new link in the menu
+       $(mPath + 'a-show-messages').hide();
+       $(mPath + 'a-delete-messages').show();
+       $(mPath + 'a-new-message').show();
+       
+       // We reset some stuffs
+       cleanNewInboxMessage();
+       
+       return false;
+}
+
+// Displays a normal message
+function displayInboxMessage(from, subject, content, status, id, date) {
+       // Generate some paths
+       var inbox = '#inbox .';
+       var one_message = inbox + 'one-message.' + id;
+       
+       // Message yet displayed!
+       if(exists(one_message))
+               return false;
+       
+       // Get the nearest element
+       var stamp = extractStamp(Date.jab2date(date));
+       var nearest = sortElementByStamp(stamp, '#inbox .one-message');
+       
+       // Get the buddy name
+       var name = getBuddyName(from).htmlEnc();
+       
+       // We generate the html code
+       var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' + 
+                               '<div class="message-head">' + 
+                                       '<div class="avatar-container">' + 
+                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="message-jid">' + name + '</div>' + 
+                                       '<div class="message-subject">' + subject.htmlEnc() + '</div>' + 
+                                       
+                                       '<div class="message-truncated">' + truncate(noLines(content), 90).htmlEnc() + '</div>' + 
+                               '</div>' + 
+                       '</div>';
+       
+       // Display the message
+       if(nearest == 0)
+               $(inbox + 'inbox-results .inbox').append(nContent);
+       else
+               $('#inbox .one-message[data-stamp=' + nearest + ']:first').before(nContent);
+       
+       // Click events
+       $(one_message + ' .message-head').click(function() {
+               if(!exists(one_message + ' .message-content'))
+                       revealInboxMessage(id, from, subject, content, name, date, status);
+               else
+                       hideInboxMessage(id);
+               
+               return false;
+       });
+       
+       // Get the user avatar
+       getAvatar(from, 'cache', 'true', 'forget');
+       
+       return true;
+}
+
+// Stores an inbox message
+function storeInboxMessage(from, subject, content, status, id, date) {
+       // Initialize the XML data
+       var xml = '<message><id>' + id.htmlEnc().htmlEnc() + '</id><date>' + date.htmlEnc().htmlEnc() + '</date><from>' + from.htmlEnc().htmlEnc() + '</from><subject>' + subject.htmlEnc().htmlEnc() + '</subject><status>' + status.htmlEnc().htmlEnc() + '</status><content>' + content.htmlEnc().htmlEnc() + '</content>';
+       
+       // End the XML data
+       xml += '</message>';
+       
+       // Store this message!
+       setDB('inbox', id, xml);
+}
+
+// Removes a given normal message
+function deleteInboxMessage(id) {
+       // Remove the message from the inbox
+       $('#inbox .one-message.' + id).remove();
+       
+       // Remove the message from the database
+       removeDB('inbox', id);
+       
+       // Check the unread messages
+       checkInboxMessages();
+       
+       // Store the new inbox
+       storeInbox();
+       
+       return false;
+}
+
+// Removes all the inbox messages
+function purgeInbox() {
+       // Remove all the messages from the database
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored message
+               if(explodeThis('_', current, 0) == 'inbox')
+                       removeDB('inbox', explodeThis('_', current, 1));
+       }
+       
+       // Prevent the database lag
+       $(document).oneTime(100, function() {
+               // Store the new inbox
+               storeInbox();
+               
+               // Remove all the messages from the inbox
+               $('#inbox .one-message').remove();
+               
+               // Reload the inbox
+               loadInbox();
+       });
+       
+       return false;
+}
+
+// Checks if there are new messages to be notified
+function checkInboxMessages() {
+       // Selectors
+       var inbox_link = '#top-content a.inbox-hidable';
+       var no_results = '#inbox .inbox-noresults';
+       
+       // Marker
+       var has_messages = false;
+       
+       // Read the number of unread messages
+       var unread = 0;
+       
+       // Read the local inbox database
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Database pointer
+               var current = sessionStorage.key(i);
+               
+               // Check inbox messages
+               if(explodeThis('_', current, 0) == 'inbox') {
+                       // Read the current status
+                       var status = $(XMLFromString(sessionStorage.getItem(current))).find('status').text();
+                       
+                       // Found an unread message
+                       if(status == 'unread')
+                               unread++;
+                       
+                       // Update the marker
+                       has_messages = true;
+               }
+       }
+       
+       // No message?
+       if(!has_messages)
+               $(no_results).show();
+       else
+               $(no_results).hide();
+       
+       // Reset notifications
+       $(inbox_link + ' .notify').remove();
+       
+       // Any unread message?
+       if(unread) {
+               // Notify the user
+               $(inbox_link).prepend('<div class="notify one-counter" data-counter="' + unread + '">' + unread + '</div>');
+               
+               // Update the title
+               updateTitle();
+               
+               return true;
+       }
+       
+       // Anyway, update the title
+       updateTitle();
+       
+       return false;
+}
+
+// Reveal a normal message content
+function revealInboxMessage(id, from, subject, content, name, date, status) {
+       // Message path
+       var all_message = '#inbox .one-message';
+       var one_message = all_message + '.' + id;
+       var one_content = one_message + ' .message-content';
+       
+       // We reset all the other messages
+       $(all_message + ' .message-content').remove();
+       $(all_message).removeClass('message-reading');
+       
+       // Message content
+       var html = 
+               '<div class="message-content">' + 
+                       '<div class="message-body">' + filterThisMessage(content, name, true) + '</div>' + 
+                       
+                       '<div class="message-meta">' + 
+                               '<span class="date">' + parseDate(date) + '</span>' + 
+                               
+                               '<a href="#" class="reply one-button talk-images">' + _e("Reply") + '</a>' + 
+                               '<a href="#" class="remove one-button talk-images">' + _e("Delete") + '</a>' + 
+                               
+                               '<div class="clear">' + 
+                       '</div>' + 
+               '</div>';
+       
+       // Message content
+       html += '</div>';
+       
+       $(one_message).append(html).addClass('message-reading');
+       
+       // Click events
+       $(one_content + ' a.reply').click(function() {
+               return replyInboxMessage(id, from, subject, content);
+       });
+       
+       $(one_content + ' a.remove').click(function() {
+               return deleteInboxMessage(id);
+       });
+       
+       // Unread message
+       if(status == 'unread') {
+               // Update our database
+               var xml = getDB('inbox', id).replace(/<status>unread<\/status>/i,'<status>read</status>');
+               setDB('inbox', id, xml);
+               
+               // Remove the unread class
+               $(one_message).removeClass('message-unread');
+               
+               // Send it to the server!
+               storeInbox();
+       }
+       
+       // Check the unread messages
+       checkInboxMessages();
+}
+
+// Hides a normal message content
+function hideInboxMessage(id) {
+       // Define the paths
+       var inbox = '#inbox .';
+       var one_message = inbox + 'one-message.' + id;
+       
+       // Reset this message
+       $(one_message).removeClass('message-reading');
+       $(one_message + ' .message-content').remove();
+}
+
+// Replies to a given normal message
+function replyInboxMessage(id, from, subject, body) {
+       // We switch to the writing div
+       newInboxMessage();
+       
+       // Inbox path
+       var inbox = '#inbox .';
+       
+       // Generate the body
+       var body = '\n' + '____________' + '\n\n' + truncate(body, 120);
+       
+       // We apply the generated values to the form
+       $(inbox + 'inbox-new-to-input').val(from);
+       $(inbox + 'inbox-new-subject-input').val(subject);
+       
+       $(document).oneTime(10, function() {
+               $(inbox + 'inbox-new-textarea').val(body).focus().selectRange(1, 0);
+       });
+       
+       return false;
+}
+
+// Loads the inbox messages
+function loadInbox() {
+       // Read the local database
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored message
+               if(explodeThis('_', current, 0) == 'inbox') {
+                       // Get the current value
+                       var value = $(XMLFromString(sessionStorage.getItem(current)));
+                       
+                       // Display the current message
+                       displayInboxMessage(
+                                               value.find('from').text().revertHtmlEnc(),
+                                               value.find('subject').text().revertHtmlEnc(),
+                                               value.find('content').text().revertHtmlEnc(),
+                                               value.find('status').text().revertHtmlEnc(),
+                                               value.find('id').text().revertHtmlEnc(),
+                                               value.find('date').text().revertHtmlEnc()
+                                          );
+               }
+       }
+       
+       // Check new messages
+       checkInboxMessages();
+}
+
+// Wait event for file attaching
+function waitInboxAttach() {
+       $('#inbox .wait').show();
+}
+
+// Success event for file attaching
+function handleInboxAttach(responseXML) {
+       // Data selector
+       var dData = $(responseXML).find('jappix');
+       
+       // Process the returned data
+       if(dData.find('error').size()) {
+               openThisError(4);
+               
+               logThis('Error while attaching the file: ' + dData.find('error').text(), 1);
+       }
+       
+       else {
+               // Get the file values
+               var fName = dData.find('title').text();
+               var fType = dData.find('type').text();
+               var fURL = dData.find('href').text();
+               
+               // Hide the attach link, show the unattach one
+               $('#inbox .inbox-new-file input').hide();
+               $('#inbox .inbox-new-file').append('<a class="file ' + encodeQuotes(fileCategory(explodeThis('/', fType, 1))) + ' talk-images" href="' + encodeQuotes(fURL) + '" target="_blank">' + fName.htmlEnc() + '</a><a href="#" class="remove one-button talk-images">' + _e("Remove") + '</a>');
+               
+               // Set values to the file link
+               $('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName)
+                                                 .attr('data-attachedhref',  fURL);
+               
+               // Click events
+               $('#inbox .inbox-new-file a.remove').click(function() {
+                       $('#inbox .inbox-new-file a').remove();
+                       $('#inbox .inbox-new-file input').show();
+                       
+                       return false;
+               });
+               
+               logThis('File attached.', 3);
+       }
+       
+       // Reset the attach bubble
+       $('#inbox .inbox-new-file input[type=file]').val('');
+       $('#inbox .wait').hide();
+}
+
+// Plugin launcher
+function launchInbox() {
+       // Define the pats
+       var inbox = '#inbox .';
+       
+       // Define the buddy search vars
+       var destination = inbox + 'inbox-new-to';
+       var dHovered = destination + ' ul li.hovered:first';
+       
+       // Send the message when enter pressend
+       $(inbox + 'inbox-new input').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       if(exists(dHovered))
+                               addBuddySearch(destination, $(dHovered).attr('data-xid'));
+                       else
+                               checkInboxMessage();
+               }
+       });
+       
+       // Buddy search
+       $(inbox + 'inbox-new-to-input').keyup(function(e) {
+               if(e.keyCode != 13) {
+                       // New buddy search
+                       if((e.keyCode != 40) && (e.keyCode != 38))
+                               createBuddySearch(destination);
+                       
+                       // Navigating with keyboard in the results
+                       arrowsBuddySearch(e, destination);
+               }
+       })
+       
+       // Buddy search lost focus
+       .blur(function() {
+               if(!$(destination + ' ul').attr('mouse-hover'))
+                       resetBuddySearch(destination);
+       })
+       
+       // Buddy search got focus
+       .focus(function() {
+               var value = $(this).val();
+               
+               // Add a comma at the end
+               if(value && !value.match(/^(.+)((,)(\s)?)$/))
+                       $(this).val(value + ', ');
+       });
+       
+       // Click events
+       $(inbox + 'a-delete-messages').click(purgeInbox);
+       $(inbox + 'a-new-message').click(newInboxMessage);
+       $(inbox + 'a-show-messages').click(showInboxMessages);
+       $(inbox + 'inbox-new-send a').click(checkInboxMessage);
+       
+       $(inbox + 'bottom .finish').click(function() {
+               return closeInbox();
+       });
+       
+       // File upload
+       var attach_options = {
+               dataType:       'xml',
+               beforeSubmit:   waitInboxAttach,
+               success:        handleInboxAttach
+       };
+       
+       // Upload form submit event
+       $('#inbox .inbox-new-file').submit(function() {
+               if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type=file]').val())
+                       $(this).ajaxSubmit(attach_options);
+               
+               return false;
+       });
+       
+       // Upload input change event
+       $('#inbox .inbox-new-file input[type=file]').change(function() {
+               if($('#inbox .wait').is(':hidden') && $(this).val())
+                       $('#inbox .inbox-new-file').ajaxSubmit(attach_options);
+               
+               return false;
+       });
+}
diff --git a/jappixmini/jappix/js/integratebox.js b/jappixmini/jappix/js/integratebox.js
new file mode 100644 (file)
index 0000000..214b3d7
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+
+Jappix - An open social platform
+These are the integratebox JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/12/11
+
+*/
+
+// Opens the integratebox popup
+function openIntegrateBox() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Media viewer") + '</div>' + 
+       
+       '<div class="content"></div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish close">' + _e("Close") + '</a>' + 
+               '<a href="#" class="finish next disabled" title="' + _e("Next") + '">&gt;</a>' + 
+               '<a href="#" class="finish previous disabled" title="' + _e("Previous") + '">&lt;</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('integratebox', html);
+       
+       // Associate the events
+       launchIntegratebox();
+}
+
+// Closes the integratebox popup
+function closeIntegrateBox() {
+       // Destroy the popup
+       destroyPopup('integratebox');
+       
+       return false;
+}
+
+// Generates the integratebox HTML code
+function codeIntegrateBox(serv, url) {
+       var code = '';
+       
+       // Protocol to use
+       var protocol = 'http';
+       
+       if(isHTTPS())
+               protocol = 'https';
+       
+       // Legacy browser
+       var legacy = false;
+       
+       if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
+               legacy = true;
+       
+       // Switch to get the good DOM code
+       switch(serv) {
+               case 'youtube':
+                       if(legacy)
+                               code = '<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/' + url + '&amp;autoplay=1"></param><embed src="http://www.youtube.com/v/' + encodeQuotes(url) + '&amp;autoplay=1" type="application/x-shockwave-flash" width="640" height="385"></embed></object>';
+                       else
+                               code = '<object width="640" height="385" data="' + encodeQuotes(protocol) + '://www.youtube.com/embed/' + encodeQuotes(url) + '?autoplay=1" type="text/html"><a href="http://www.youtube.com/watch?v=' + encodeQuotes(url) + '" target="_blank">http://www.youtube.com/watch?v=' + encodeQuotes(url) + '</a></object>';
+                       
+                       break;
+               
+               case 'dailymotion':
+                       code = '<object width="640" height="385"><param name="movie" value="http://www.dailymotion.com/swf/video/' + url + '&amp;autoplay=1"></param><param name="allowFullScreen" value="false"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/' + encodeQuotes(url) + '&amp;autoplay=1" width="640" height="385" allowfullscreen="true" allowscriptaccess="always"></embed></object>';
+                       
+                       break;
+               
+               case 'vimeo':
+                       code = '<object width="640" height="385"><param name="allowfullscreen" value="true" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="385"></embed></object>';
+                       
+                       break;
+               
+               case 'theora':
+               case 'video':
+                       code = '<video width="640" height="385" src="' + encodeQuotes(url) + '" controls autoplay><a href="' + encodeQuotes(url) + '" target="_blank">' + encodeQuotes(url) + '</a></video>';
+                       
+                       break;
+               
+               case 'vorbis':
+               case 'audio':
+                       code = '<audio src="' + encodeQuotes(url) + '" controls autoplay><a href="' + encodeQuotes(url) + '" target="_blank">' + encodeQuotes(url) + '</a></audio>';
+                       
+                       break;
+               
+               case 'image':
+                       code = '<a href="' + encodeQuotes(url) + '" target="_blank"><img alt="" src="' + encodeQuotes(url) + '" /></a>';
+               
+                       break;
+       }
+       
+       return code;
+}
+
+// Applies a given integratebox element
+function applyIntegrateBox(url, service, url_list, services_list, comments_e_list, comments_n_list, width_style) {
+       // Close the integratebox
+       closeIntegrateBox();
+       
+       // Media integration not wanted?
+       if(getDB('options', 'integratemedias') == '0')
+               return true;
+       
+       // Apply the HTML code
+       var dom_code = codeIntegrateBox(service, url);
+       
+       // Any code: apply it!
+       if(dom_code) {
+               // We show the integratebox
+               openIntegrateBox();
+               
+               // We add the code to the DOM
+               $('#integratebox .content').prepend('<div class="one-media">' + dom_code + '</div>');
+               
+               // Image waiting icon
+               if(service == 'image') {
+                       var waitItem = $('#integratebox .wait');
+                       
+                       // Show it while it is loading
+                       waitItem.show();
+                       
+                       // Hide it when it is loaded
+                       $('#integratebox img').load(function() {
+                               waitItem.hide();
+                               
+                               // Center the image vertically
+                               $(this).oneTime(10, function() {
+                                       $(this).css('margin-top', (($('#integratebox .content').height() - $(this).height()) / 2));
+                               });
+                       });
+               }
+               
+               // Large style?
+               var comments_id = genID();
+               
+               if(width_style == 'large') {
+                       // Make the popup large
+                       $('#integratebox .popup').addClass('large');
+                       
+                       // Add the right content
+                       $('#integratebox .content').after(
+                               '<div class="comments" data-id="' + encodeQuotes(comments_id) + '">' + 
+                                       '<div class="comments-content">' + 
+                                               '<div class="one-comment loading"><span class="icon talk-images"></span>' + _e("Loading comments...") + '</div>' + 
+                                       '</div>' + 
+                               '</div>'
+                       );
+               }
+               
+               // Previous and next items?
+               var url_array = stringToArray(url_list);
+               var services_array = stringToArray(services_list);
+               var comments_e_array = stringToArray(comments_e_list);
+               var comments_n_array = stringToArray(comments_n_list);
+               var index = indexArrayValue(url_array, url);
+               
+               // Any comments?
+               if(exists('#integratebox .comments')) {
+                       if(comments_e_array[index] && comments_n_array[index])
+                               getCommentsMicroblog(comments_e_array[index], comments_n_array[index], comments_id);
+                       else
+                               $('#integratebox .comments .comments-content').html('<div class="one-comment loading"><span class="icon talk-images"></span>' + _e("Comments locked!") + '</div>');
+               }
+                       
+               // Get the previous values
+               var previous_url = url_array[index - 1];
+               var previous_services = services_array[index - 1];
+               
+               // Get the next values
+               var next_url = url_array[index + 1];
+               var next_services = services_array[index + 1];
+               
+               // Enable/disable buttons
+               if(previous_url && previous_services)
+                       $('#integratebox .bottom .finish.previous').removeClass('disabled');
+               else
+                       $('#integratebox .bottom .finish.previous').addClass('disabled');
+               
+               if(next_url && next_services)
+                       $('#integratebox .bottom .finish.next').removeClass('disabled');
+               else
+                       $('#integratebox .bottom .finish.next').addClass('disabled');
+               
+               // Click events
+               $('#integratebox .bottom .finish.previous, #integratebox .bottom .finish.next').click(function() {
+                       // Not acceptable?
+                       if($(this).is('.disabled'))
+                               return false;
+                       
+                       // Apply the event!
+                       if($(this).is('.previous'))
+                               applyIntegrateBox(previous_url, previous_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
+                       else
+                               applyIntegrateBox(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
+                       
+                       return false;
+               });
+               
+               if(width_style == 'large')
+                       $('#integratebox .content a:has(img)').click(function() {
+                               if(next_url && next_services)
+                                       applyIntegrateBox(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
+                               
+                               return false;
+                       });
+               
+               return false;
+       }
+       
+       // Nothing: return true to be able to open the URL in a new tab
+       return true;
+}
+
+// Checks whether the file ext can use integratebox or not
+function canIntegrateBox(ext) {
+       // Can use?
+       if(ext && ((ext == 'jpg') || (ext == 'jpeg') || (ext == 'png') || (ext == 'gif') || (ext == 'ogg') || (ext == 'oga') || (ext == 'ogv')))
+               return true;
+       
+       return false;
+}
+
+// Filters a string to apply the integratebox links
+function filterIntegrateBox(data) {
+       // Encapsulates the string into two <div /> elements
+       var xml = $('<div><div>' + data + '</div></div>').contents();
+       
+       // Loop the <a /> elements
+       $(xml).find('a').each(function() {
+               // Initialize this element
+               var href = $(this).attr('href');
+               var to, url, service, event;
+               
+               // XMPP ID
+               if(href.match(/^xmpp:(.+)/i))
+                       to = RegExp.$1;
+               
+               // YouTube video box
+               else if(href.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim)) {
+                       url = RegExp.$8;
+                       service = 'youtube';
+               }
+               
+               // Dailymotion video box
+               else if(href.match(/(\w{3,5})(:)(\S+)\.dailymotion\.com\/video\/([\w\-]+)((\#[\w\-]+)|\s|$)/gim)) {
+                       url = RegExp.$4;
+                       service = 'dailymotion';
+               }
+               
+               // Vimeo video box
+               else if(href.match(/((\w{3,5})(:)(\S+)(vimeo|www\.vimeo)\.com\/([\w\-]+))/gim)) {
+                       url = RegExp.$1;
+                       service = 'vimeo';
+               }
+               
+               // Theora video box
+               else if(href.match(/((\w{3,5})(:)(\S+)(\.)(ogv|ogg))/gim)) {
+                       url = RegExp.$1;
+                       service = 'theora';
+               }
+               
+               // Vorbis audio box
+               else if(href.match(/((\w{3,5})(:)(\S+)(\.oga))/gim)) {
+                       url = RegExp.$1;
+                       service = 'vorbis';
+               }
+               
+               // Image box
+               else if(href.match(/((\w{3,5})(:)(\S+)(\.)(jpg|jpeg|png|gif|tif|bmp))/gim)) {
+                       url = RegExp.$1;
+                       service = 'image';
+               }
+               
+               // Define the good event
+               if(to)
+                       event = 'xmppLink(\'' + encodeOnclick(to) + '\')';
+               else if(url && service)
+                       event = 'applyIntegrateBox(\'' + encodeOnclick(url) + '\', \'' + encodeOnclick(service) + '\')';
+               
+               // Any click event to apply?
+               if(event) {
+                       // Regenerate the link element (for onclick)
+                       var new_a = '<a';
+                       var element_a = (this);
+                       
+                       // Attributes
+                       $(element_a.attributes).each(function(index) {
+                               // Read the current attribute
+                               var current_attr = element_a.attributes[index];
+                               
+                               // Apply the current attribute
+                               new_a += ' ' + encodeQuotes(current_attr.name) + '="' + encodeQuotes(current_attr.value) + '"';
+                       });
+                       
+                       // Add onclick attribute
+                       new_a += ' onclick="return ' + event + ';"';
+                       
+                       // Value
+                       new_a += '>' + $(this).text().htmlEnc() + '</a>';
+                       
+                       // Replace it!
+                       $(this).replaceWith(new_a);
+               }
+       });
+       
+       // Regenerate the HTML code (include string into a div to be readable)
+       var string = $(xml).html();
+       
+       return string;
+}
+
+// Plugin launcher
+function launchIntegratebox() {
+       // Click event
+       $('#integratebox .bottom .finish.close').click(closeIntegrateBox);
+}
+
+// Plugin keyup event
+$(document).keyup(function(e) {
+       // Previous item?
+       if((exists('#integratebox .bottom .finish.previous:not(.disabled)')) && (e.keyCode == 37)) {
+               $('#integratebox .bottom .finish.previous').click();
+               
+               return false;
+       }
+       
+       // Next item?
+       if((exists('#integratebox .bottom .finish.next:not(.disabled)')) && (e.keyCode == 39)) {
+               $('#integratebox .bottom .finish.next').click();
+               
+               return false;
+       }
+});
diff --git a/jappixmini/jappix/js/interface.js b/jappixmini/jappix/js/interface.js
new file mode 100644 (file)
index 0000000..e4a0db5
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+
+Jappix - An open social platform
+These are the interface JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Changes the title of the document
+function pageTitle(title) {
+       // Anonymous mode?
+       var head_name = getName();
+       
+       if(isAnonymous())
+               head_name = ANONYMOUS_ROOM + ' (' + _e("anonymous mode") + ')';
+       
+       // We change the title to give essential informations
+       switch(title) {
+               case 'home':
+                       document.title = SERVICE_NAME + ' • ' + _e("An open social network");
+                       
+                       break;
+               
+               case 'talk':
+                       document.title = 'Jappix • ' + head_name;
+                       
+                       break;
+               
+               case 'new':
+                       document.title = '[' + pendingEvents() + '] Jappix • ' + head_name;
+                       
+                       break;
+               
+               case 'wait':
+                       document.title = 'Jappix • ' + _e("Please wait...");
+                       
+                       break;
+       }
+}
+
+// Creates a general-wait item
+function showGeneralWait() {
+       // Item exists?
+       if(exists('#general-wait'))
+               return false;
+       
+       // Generate the HTML code
+       var html = 
+       '<div id="general-wait" class="removable">' + 
+               '<div class="general-wait-content wait-big"></div>' + 
+       '</div>';
+       
+       // Append the HTML code
+       $('body').append(html);
+       
+       return true;
+}
+
+// Removes the general-wait item
+function removeGeneralWait() {
+       $('#general-wait').remove();
+}
+
+// Generates a file upload valid form content
+function generateFileShare() {
+       return  '<input type="hidden" name="MAX_FILE_SIZE" value="' + encodeQuotes(JAPPIX_MAX_FILE_SIZE) + '">' + 
+               '<input type="hidden" name="user" value="' + encodeQuotes(getXID()) + '" />' + 
+               '<input type="hidden" name="location" value="' + encodeQuotes(generateURL(JAPPIX_LOCATION)) + '" />' + 
+               '<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' + 
+               '<input type="file" name="file" required="" />' + 
+               '<input type="submit" value="' + _e("Send") + '" />';
+}
+
+// Switches to the given chan
+function switchChan(id) {
+       if(exists('#' + id)) {
+               // We show the page-engine content
+               $('.page-engine-chan').hide();
+               $('#' + id).show();
+               
+               // We edit the tab switcher
+               $('#page-switch .switcher').removeClass('activechan').addClass('chan');
+               $('#page-switch .' + id).addClass('activechan').removeClass('chan');
+               
+               // Scroll down to the last message
+               if(id != 'channel')
+                       autoScroll(id);
+               
+               // Manage input focus
+               inputFocus();
+       }
+       
+       return false;
+}
+
+// Loads the complete chat switcher
+function loadChatSwitch() {
+       // Path
+       var more_content = '#page-switch .more-content';
+       
+       // Yet displayed?
+       if(exists(more_content))
+               return closeBubbles();
+       
+       // Add the bubble
+       showBubble(more_content);
+       
+       // Append the content
+       $('#page-switch .more').append(
+               '<div class="more-content bubble removable">' + 
+                       $('#page-switch .chans').html() + 
+               '</div>'
+       );
+       
+       return false;
+}
+
+// Puts the selected smiley in the good page-engine input
+function insertSmiley(smiley, hash) {
+       // We define the variables
+       var selector = $('#' + hash + ' .message-area');
+       var oValue = selector.val();
+       
+       // Any old value?
+       if(oValue && !oValue.match(/^(.+)(\s)+$/))
+               oValue += ' ';
+       
+       var nValue = oValue + smiley + ' ';
+       
+       // Put the new value and focus on it
+       $(document).oneTime(10, function() {
+               selector.val(nValue).focus();
+       });
+       
+       return false;
+}
+
+// Deletes all the associated elements of the chat we want to remove
+function deleteThisChat(hash) {
+       $('#' + hash + ', #page-switch .' + hash).remove();
+}
+
+// Closes the given chat
+function quitThisChat(xid, hash, type) {
+       if(type == 'groupchat') {
+               // Send our unavailable presence
+               sendPresence(xid + '/' + getMUCNick(hash), 'unavailable');
+               
+               // Remove all presence database entries for this groupchat
+               for(var i = 0; i < sessionStorage.length; i++) {
+                       // Get the pointer values
+                       var current = sessionStorage.key(i);
+                       var cXID = explodeThis('_', current, 1);
+                       
+                       // If the pointer is on a presence from this groupchat
+                       if((explodeThis('_', current, 0) == 'presence') && (bareXID(cXID) == xid)) {
+                               // Generate the hash for the current XID
+                               var cHash = hex_md5(cXID);
+                               
+                               // Disable the message textarea
+                               $('#' + cHash + ' .message-area').attr('disabled', true);
+                               
+                               // Remove the presence for this XID
+                               removeDB('presence', cXID);
+                               presenceFunnel(cXID, cHash);
+                       }
+               }
+       }
+       
+       else
+               chatStateSend('gone', xid, hash);
+       
+       // Get the chat ID which is before
+       var previous = $('#' + hash).prev().attr('id');
+       
+       // Remove the chat
+       deleteThisChat(hash);
+       
+       // Reset the switcher
+       if(!exists('#page-switch .switcher.activechan'))
+               switchChan(previous);
+       
+       // Reset the notifications
+       chanCleanNotify(hash);
+       
+       return false;
+}
+
+// Generates the chat logs
+function generateChatLog(xid, hash) {
+       // Get the main values
+       var path = '#' + hash + ' .';
+       var content = $(path + 'content').clone().contents();
+       var avatar = $(path + 'top .avatar-container:first').html();
+       var nick = $(path + 'top .bc-name').text();
+       var date = getXMPPTime('local');
+       var type = $('#' + hash).attr('data-type');
+       
+       // Filter the content smileys
+       $(content).find('img.emoticon').each(function() {
+               $(this).replaceWith($(this).attr('alt'));
+       });
+       
+       // Remove the useless attributes
+       $(content).removeAttr('data-type').removeAttr('data-stamp');
+       
+       // Remove the content avatars
+       $(content).find('.avatar-container').remove();
+       
+       // Remove the content click events
+       $(content).find('a').removeAttr('onclick');
+       
+       // Extract the content HTML code
+       content = $(content).parent().html();
+       
+       // No avatar?
+       if(!avatar || !avatar.match(/data:/))
+               avatar = 'none';
+       
+       // POST the values to the server
+       $.post('./php/generate-chat.php', { content: content, xid: xid, nick: nick, avatar: avatar, date: date, type: type }, function(data) {
+               // Handled!
+               $(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./php/download-chat.php?id=' + data + '" target="_blank">' + _e("Download file!") + '</a>');
+       });
+       
+       return false;
+}
+
+// Notifies the user from a new incoming message
+function messageNotify(hash, type) {
+       // Initialize the vars
+       var chat_switch = '#page-switch .';
+       var tested = chat_switch + hash;
+       var active = $(tested).hasClass('activechan');
+       
+       // We notify the user if he has not the focus on the chat
+       if(!active || !isFocused()) {
+               if(!active) {
+                       if(type == 'personnal')
+                               $(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
+                       else if(type == 'unread')
+                               $(tested).addClass('chan-unread');
+               }
+               
+               // Count the number of pending messages
+               var pending = 1;
+               
+               if(exists('#' + hash + '[data-counter]'))
+                       pending = parseInt($('#' + hash).attr('data-counter')) + 1;
+               
+               $('#' + hash).attr('data-counter', pending);
+       }
+       
+       // Update the page title
+       updateTitle();
+}
+
+// Returns the number of pending events
+function pendingEvents() {
+       // Count the number of notifications
+       var number = 0;
+       
+       $('.one-counter[data-counter]').each(function() {
+               number = number + parseInt($(this).attr('data-counter'));
+       });
+       
+       return number;
+}
+
+// Updates the page title
+function updateTitle() {
+       // Any pending events?
+       if(exists('.one-counter[data-counter]'))
+               pageTitle('new');
+       else
+               pageTitle('talk');
+}
+
+// Cleans the given chat notifications
+function chanCleanNotify(hash) {
+       // We remove the class that tell the user of a new message
+       var chat_switch = '#page-switch .';
+       $(chat_switch + hash).removeClass('chan-newmessage chan-unread');
+       
+       // We reset the global notifications if no more unread messages
+       if(!$(chat_switch + 'chans .chan-newmessage').size())
+               $(chat_switch + 'more-button').removeClass('chan-newmessage');
+       
+       // We reset the chat counter
+       $('#' + hash).removeAttr('data-counter');
+       
+       // Update the page title
+       updateTitle();
+}
+
+// Scrolls to the last chat message
+function autoScroll(hash) {
+       // Avoid a JS error
+       if(exists('#' + hash)) {
+               var container = document.getElementById('chat-content-' + hash);
+               
+               // Scroll down!
+               container.scrollTop = container.scrollHeight;
+       }
+}
+
+// Shows all the buddies in the buddy-list
+function showAllBuddies(from) {
+       // Put a marker
+       BLIST_ALL = true;
+       
+       // We switch the two modes
+       $('.buddy-conf-more-display-unavailable').hide();
+       $('.buddy-conf-more-display-available').show();
+       
+       // Security: reset all the groups toggle event
+       $('#buddy-list .group-buddies').show();
+       $('#buddy-list .group span').text('-');
+       
+       // We show the disconnected buddies
+       $('.hidden-buddy').show();
+       
+       // We show all the groups
+       $('#buddy-list .one-group').show();
+       
+       if(SEARCH_FILTERED)
+               funnelFilterBuddySearch();
+       
+       // Store this in the options
+       if((from == 'roster') && loadedOptions()) {
+               setDB('options', 'roster-showall', '1');
+               storeOptions();
+       }
+}
+
+// Shows only the online buddies in the buddy-list
+function showOnlineBuddies(from) {
+       // Remove the marker
+       BLIST_ALL = false;
+       
+       // We switch the two modes
+       $('.buddy-conf-more-display-available').hide();
+       $('.buddy-conf-more-display-unavailable').show();
+       
+       // Security: reset all the groups toggle event
+       $('#buddy-list .group-buddies').show();
+       $('#buddy-list .group span').text('-');
+       
+       // We hide the disconnected buddies
+       $('.hidden-buddy').hide();
+       
+       // We check the groups to hide
+       updateGroups();
+       
+       if(SEARCH_FILTERED)
+               funnelFilterBuddySearch();
+       
+       // Store this in the options
+       if((from == 'roster') && loadedOptions()) {
+               setDB('options', 'roster-showall', '0');
+               storeOptions();
+       }
+}
+
+// Focuses on the right input
+function inputFocus() {
+       // No popup shown
+       if(!exists('.popup'))
+               $(document).oneTime(10, function() {
+                       $('.focusable:visible:first').focus();
+               });
+}
+
+// Plugin launcher
+function launchInterface() {
+       // Focus on the first visible input
+       $(window).focus(inputFocus);
+}
+
+// Launch this plugin!
+$(document).ready(launchInterface);
diff --git a/jappixmini/jappix/js/iq.js b/jappixmini/jappix/js/iq.js
new file mode 100644 (file)
index 0000000..1e16292
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+
+Jappix - An open social platform
+These are the IQ JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+// Handles an incoming IQ packet
+function handleIQ(iq) {
+       // Gets the IQ content
+       var iqNode = iq.getNode();
+       var iqFrom = fullXID(getStanzaFrom(iq));
+       var iqID = iq.getID();
+       var iqQueryXMLNS = iq.getQueryXMLNS();
+       var iqQuery = iq.getQuery();
+       var iqType = iq.getType();
+       
+       // Build the response
+       var iqResponse = new JSJaCIQ();
+       
+       iqResponse.setID(iqID);
+       iqResponse.setTo(iqFrom);
+       iqResponse.setType('result');
+       
+       // OOB request
+       if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
+               /* REF: http://xmpp.org/extensions/xep-0066.html */
+               
+               handleOOB(iqFrom, iqID, 'iq', iqNode);
+               
+               logThis('Received IQ OOB request: ' + iqFrom);
+       }
+       
+       // OOB reply
+       else if(getDB('send/url', iqID)) {
+               // Get the values
+               var oob_url = getDB('send/url', iqID);
+               var oob_desc = getDB('send/desc', iqID);
+               var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
+               
+               // Error?
+               if($(iqNode).find('error').size()) {
+                       // Rejected?
+                       if($(iqNode).find('error not-acceptable').size())
+                               newNotification('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
+                       
+                       // Failed?
+                       else
+                               newNotification('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
+                       
+                       // Remove the file
+                       $.get(oob_url + '&action=remove');
+               }
+               
+               // Success?
+               else if(iqType == 'result')
+                       newNotification('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
+       }
+       
+       // Software version query
+       else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0092.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_VERSION);
+               
+               iqQuery.appendChild(iq.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix'));
+               iqQuery.appendChild(iq.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
+               iqQuery.appendChild(iq.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
+               
+               con.send(iqResponse);
+               
+               logThis('Received software version query: ' + iqFrom);
+       }
+       
+       // Last activity query
+       else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0012.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_LAST);
+               iqQuery.setAttribute('seconds', getLastActivity());
+               
+               con.send(iqResponse);
+               
+               logThis('Received last activity query: ' + iqFrom);
+       }
+       
+       // Privacy lists push
+       else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set')) {
+               // REF : http://xmpp.org/extensions/xep-0016.html
+               
+               // Roster push
+               con.send(iqResponse);
+               
+               // Get the lists
+               $(iqQuery).find('list').each(function() {
+                       getPrivacy($(this).attr('name'));
+               });
+               
+               logThis('Received privacy lists push: ' + iqFrom);
+       }
+       
+       // Roster push
+       else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set')) {
+               // REF : http://xmpp.org/extensions/xep-0092.html
+               
+               // Roster push
+               con.send(iqResponse);
+               
+               // Get the values
+               $(iqQuery).find('item').each(function() {
+                       parseRoster($(this), 'presence');
+               });
+               
+               logThis('Received roster push: ' + iqFrom);
+       }
+       
+       // Roster Item Exchange query
+       else if($(iqNode).find('x[xmlns=' + NS_ROSTERX + ']').size()) {
+               // Open a new notification
+               newNotification('rosterx', iqFrom, [iqNode], '');
+               
+               logThis('Roster Item Exchange from: ' + iqFrom);
+       }
+       
+       // Disco info query
+       else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0030.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
+               
+               // We set the name of the client
+               iqQuery.appendChild(iq.buildNode('identity', {
+                       'category': 'client',
+                       'type': 'web',
+                       'name': 'Jappix',
+                       'xmlns': NS_DISCO_INFO
+               }));
+               
+               // We set all the supported features
+               var fArray = myDiscoInfos();
+               
+               for(i in fArray)
+                       iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i], 'xmlns': NS_DISCO_INFO}));
+               
+               con.send(iqResponse);
+               
+               logThis('Received disco#infos query: ' + iqFrom);
+       }
+       
+       // User time query
+       else if($(iqNode).find('time').size() && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0202.html */
+               
+               var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
+               iqTime.appendChild(iq.buildNode('tzo', {'xmlns': NS_URN_TIME}, getDateTZO()));
+               iqTime.appendChild(iq.buildNode('utc', {'xmlns': NS_URN_TIME}, getXMPPTime('utc')));
+               
+               con.send(iqResponse);
+               
+               logThis('Received local time query: ' + iqFrom);
+       }
+       
+       // Ping
+       else if($(iqNode).find('ping').size() && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0199.html */
+               
+               con.send(iqResponse);
+               
+               logThis('Received a ping: ' + iqFrom);
+       }
+       
+       // Not implemented
+       else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
+               // Append stanza content
+               for(var i = 0; i < iqNode.childNodes.length; i++)
+                       iqResponse.getNode().appendChild(iqNode.childNodes.item(i).cloneNode(true));
+               
+               // Append error content
+               var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
+               iqError.appendChild(iq.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
+               iqError.appendChild(iq.buildNode('text', {'xmlns': NS_STANZAS}, _e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
+               
+               con.send(iqResponse);
+               
+               logThis('Received an unsupported IQ query from: ' + iqFrom);
+       }
+}
diff --git a/jappixmini/jappix/js/jquery.datepicker.js b/jappixmini/jappix/js/jquery.datepicker.js
new file mode 100644 (file)
index 0000000..d4786f9
--- /dev/null
@@ -0,0 +1,896 @@
+/*\r
+\r
+Jappix - An open social platform\r
+These are the datepicker JS script\r
+\r
+-------------------------------------------------\r
+\r
+Licenses: MIT, GPL, AGPL\r
+Authors: Stefan Petre, Vanaryon\r
+Last revision: 19/12/10\r
+\r
+*/\r
+\r
+(function ($) {\r
+       var DatePicker = function () {\r
+               var     ids = {},\r
+                       views = {\r
+                               years: 'datepickerViewYears',\r
+                               moths: 'datepickerViewMonths',\r
+                               days: 'datepickerViewDays'\r
+                       },\r
+                       tpl = {\r
+                               wrapper: '<div class="datepicker"><div class="datepickerBorderT" /><div class="datepickerBorderB" /><div class="datepickerBorderL" /><div class="datepickerBorderR" /><div class="datepickerBorderTL" /><div class="datepickerBorderTR" /><div class="datepickerBorderBL" /><div class="datepickerBorderBR" /><div class="datepickerContainer"><table cellspacing="0" cellpadding="0"><tbody><tr></tr></tbody></table></div></div>',\r
+                               head: [\r
+                                       '<td>',\r
+                                       '<table cellspacing="0" cellpadding="0">',\r
+                                               '<thead>',\r
+                                                       '<tr>',\r
+                                                               '<th class="datepickerGoPrev"><a href="#"><span><%=prev%></span></a></th>',\r
+                                                               '<th colspan="6" class="datepickerMonth"><a href="#"><span></span></a></th>',\r
+                                                               '<th class="datepickerGoNext"><a href="#"><span><%=next%></span></a></th>',\r
+                                                       '</tr>',\r
+                                                       '<tr class="datepickerDoW">',\r
+                                                               '<th><span><%=week%></span></th>',\r
+                                                               '<th><span><%=day1%></span></th>',\r
+                                                               '<th><span><%=day2%></span></th>',\r
+                                                               '<th><span><%=day3%></span></th>',\r
+                                                               '<th><span><%=day4%></span></th>',\r
+                                                               '<th><span><%=day5%></span></th>',\r
+                                                               '<th><span><%=day6%></span></th>',\r
+                                                               '<th><span><%=day7%></span></th>',\r
+                                                       '</tr>',\r
+                                               '</thead>',\r
+                                       '</table></td>'\r
+                               ],\r
+                               space : '<td class="datepickerSpace"><div></div></td>',\r
+                               days: [\r
+                                       '<tbody class="datepickerDays">',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[0].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[0].days[0].classname%>"><a href="#"><span><%=weeks[0].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[1].classname%>"><a href="#"><span><%=weeks[0].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[2].classname%>"><a href="#"><span><%=weeks[0].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[3].classname%>"><a href="#"><span><%=weeks[0].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[4].classname%>"><a href="#"><span><%=weeks[0].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[5].classname%>"><a href="#"><span><%=weeks[0].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[0].days[6].classname%>"><a href="#"><span><%=weeks[0].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[1].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[1].days[0].classname%>"><a href="#"><span><%=weeks[1].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[1].classname%>"><a href="#"><span><%=weeks[1].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[2].classname%>"><a href="#"><span><%=weeks[1].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[3].classname%>"><a href="#"><span><%=weeks[1].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[4].classname%>"><a href="#"><span><%=weeks[1].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[5].classname%>"><a href="#"><span><%=weeks[1].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[1].days[6].classname%>"><a href="#"><span><%=weeks[1].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[2].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[2].days[0].classname%>"><a href="#"><span><%=weeks[2].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[1].classname%>"><a href="#"><span><%=weeks[2].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[2].classname%>"><a href="#"><span><%=weeks[2].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[3].classname%>"><a href="#"><span><%=weeks[2].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[4].classname%>"><a href="#"><span><%=weeks[2].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[5].classname%>"><a href="#"><span><%=weeks[2].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[2].days[6].classname%>"><a href="#"><span><%=weeks[2].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[3].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[3].days[0].classname%>"><a href="#"><span><%=weeks[3].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[1].classname%>"><a href="#"><span><%=weeks[3].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[2].classname%>"><a href="#"><span><%=weeks[3].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[3].classname%>"><a href="#"><span><%=weeks[3].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[4].classname%>"><a href="#"><span><%=weeks[3].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[5].classname%>"><a href="#"><span><%=weeks[3].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[3].days[6].classname%>"><a href="#"><span><%=weeks[3].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[4].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[4].days[0].classname%>"><a href="#"><span><%=weeks[4].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[1].classname%>"><a href="#"><span><%=weeks[4].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[2].classname%>"><a href="#"><span><%=weeks[4].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[3].classname%>"><a href="#"><span><%=weeks[4].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[4].classname%>"><a href="#"><span><%=weeks[4].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[5].classname%>"><a href="#"><span><%=weeks[4].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[4].days[6].classname%>"><a href="#"><span><%=weeks[4].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<th class="datepickerWeek"><a href="#"><span><%=weeks[5].week%></span></a></th>',\r
+                                                       '<td class="<%=weeks[5].days[0].classname%>"><a href="#"><span><%=weeks[5].days[0].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[1].classname%>"><a href="#"><span><%=weeks[5].days[1].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[2].classname%>"><a href="#"><span><%=weeks[5].days[2].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[3].classname%>"><a href="#"><span><%=weeks[5].days[3].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[4].classname%>"><a href="#"><span><%=weeks[5].days[4].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[5].classname%>"><a href="#"><span><%=weeks[5].days[5].text%></span></a></td>',\r
+                                                       '<td class="<%=weeks[5].days[6].classname%>"><a href="#"><span><%=weeks[5].days[6].text%></span></a></td>',\r
+                                               '</tr>',\r
+                                       '</tbody>'\r
+                               ],\r
+                               months: [\r
+                                       '<tbody class="<%=className%>">',\r
+                                               '<tr>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[0]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[1]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[2]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[3]%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[4]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[5]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[6]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[7]%></span></a></td>',\r
+                                               '</tr>',\r
+                                               '<tr>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[8]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[9]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[10]%></span></a></td>',\r
+                                                       '<td colspan="2"><a href="#"><span><%=data[11]%></span></a></td>',\r
+                                               '</tr>',\r
+                                       '</tbody>'\r
+                               ]\r
+                       },\r
+                       defaults = {\r
+                               flat: false,\r
+                               starts: 1,\r
+                               prev: '&#9664;',\r
+                               next: '&#9654;',\r
+                               lastSel: false,\r
+                               mode: 'single',\r
+                               view: 'days',\r
+                               calendars: 1,\r
+                               format: 'Y-m-d',\r
+                               position: 'bottom',\r
+                               eventName: 'click',\r
+                               onRender: function(){return {};},\r
+                               onChange: function(){return true;},\r
+                               onShow: function(){return true;},\r
+                               onBeforeShow: function(){return true;},\r
+                               onHide: function(){return true;},\r
+                               locale: {\r
+                                       days: [_e("Sunday"), _e("Monday"), _e("Tuesday"), _e("Wednesday"), _e("Thursday"), _e("Friday"), _e("Saturday"), _e("Sunday")],\r
+                                       daysShort: [cut(_e("Sunday"), 3), cut(_e("Monday"), 3), cut(_e("Tuesday"), 3), cut(_e("Wednesday"), 3), cut(_e("Thursday"), 3), cut(_e("Friday"), 3), cut(_e("Saturday"), 3), cut(_e("Sunday"), 3)],\r
+                                       daysMin: [cut(_e("Sunday"), 2), cut(_e("Monday"), 2), cut(_e("Tuesday"), 2), cut(_e("Wednesday"), 2), cut(_e("Thursday"), 2), cut(_e("Friday"), 2), cut(_e("Saturday"), 2), cut(_e("Sunday"), 2)],\r
+                                       months: [_e("January"), _e("February"), _e("March"), _e("April"), _e("May"), _e("June"), _e("July"), _e("August"), _e("September"), _e("October"), _e("November"), _e("December")],\r
+                                       monthsShort: [cut(_e("January"), 3), cut(_e("February"), 3), cut(_e("March"), 3), cut(_e("April"), 3), cut(_e("May"), 3), cut(_e("June"), 3), cut(_e("July"), 3), cut(_e("August"), 3), cut(_e("September"), 3), cut(_e("October"), 3), cut(_e("November"), 3), cut(_e("December"), 3)],\r
+                                       weekMin: ''\r
+                               }\r
+                       },\r
+                       fill = function(el) {\r
+                               var options = $(el).data('datepicker');\r
+                               var cal = $(el);\r
+                               var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, week, days, indic, indic2, html, tblCal;\r
+                               cal.find('td>table tbody').remove();\r
+                               for (var i = 0; i < options.calendars; i++) {\r
+                                       date = new Date(options.current);\r
+                                       date.addMonths(-currentCal + i);\r
+                                       tblCal = cal.find('table').eq(i+1);\r
+                                       switch (tblCal[0].className) {\r
+                                               case 'datepickerViewDays':\r
+                                                       dow = formatDate(date, 'B, Y');\r
+                                                       break;\r
+                                               case 'datepickerViewMonths':\r
+                                                       dow = date.getFullYear();\r
+                                                       break;\r
+                                               case 'datepickerViewYears':\r
+                                                       dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5);\r
+                                                       break;\r
+                                       } \r
+                                       tblCal.find('thead tr:first th:eq(1) span').text(dow);\r
+                                       dow = date.getFullYear()-6;\r
+                                       data = {\r
+                                               data: [],\r
+                                               className: 'datepickerYears'\r
+                                       }\r
+                                       for ( var j = 0; j < 12; j++) {\r
+                                               data.data.push(dow + j);\r
+                                       }\r
+                                       html = tmpl(tpl.months.join(''), data);\r
+                                       date.setDate(1);\r
+                                       data = {weeks:[], test: 10};\r
+                                       month = date.getMonth();\r
+                                       var dow = (date.getDay() - options.starts) % 7;\r
+                                       date.addDays(-(dow + (dow < 0 ? 7 : 0)));\r
+                                       week = -1;\r
+                                       cnt = 0;\r
+                                       while (cnt < 42) {\r
+                                               indic = parseInt(cnt/7,10);\r
+                                               indic2 = cnt%7;\r
+                                               if (!data.weeks[indic]) {\r
+                                                       week = date.getWeekNumber();\r
+                                                       data.weeks[indic] = {\r
+                                                               week: week,\r
+                                                               days: []\r
+                                                       };\r
+                                               }\r
+                                               data.weeks[indic].days[indic2] = {\r
+                                                       text: date.getDate(),\r
+                                                       classname: []\r
+                                               };\r
+                                               if (month != date.getMonth()) {\r
+                                                       data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth');\r
+                                               }\r
+                                               if (date.getDay() == 0) {\r
+                                                       data.weeks[indic].days[indic2].classname.push('datepickerSunday');\r
+                                               }\r
+                                               if (date.getDay() == 6) {\r
+                                                       data.weeks[indic].days[indic2].classname.push('datepickerSaturday');\r
+                                               }\r
+                                               var fromUser = options.onRender(date);\r
+                                               var val = date.valueOf();\r
+                                               if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) {\r
+                                                       data.weeks[indic].days[indic2].classname.push('datepickerSelected');\r
+                                               }\r
+                                               if (fromUser.disabled) {\r
+                                                       data.weeks[indic].days[indic2].classname.push('datepickerDisabled');\r
+                                               }\r
+                                               if (fromUser.className) {\r
+                                                       data.weeks[indic].days[indic2].classname.push(fromUser.className);\r
+                                               }\r
+                                               data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' ');\r
+                                               cnt++;\r
+                                               date.addDays(1);\r
+                                       }\r
+                                       html = tmpl(tpl.days.join(''), data) + html;\r
+                                       data = {\r
+                                               data: options.locale.monthsShort,\r
+                                               className: 'datepickerMonths'\r
+                                       };\r
+                                       html = tmpl(tpl.months.join(''), data) + html;\r
+                                       tblCal.append(html);\r
+                               }\r
+                       },\r
+                       parseDate = function (date, format) {\r
+                               if (date.constructor == Date) {\r
+                                       return new Date(date);\r
+                               }\r
+                               var parts = date.split(/\W+/);\r
+                               var against = format.split(/\W+/), d, m, y, h, min, now = new Date();\r
+                               for (var i = 0; i < parts.length; i++) {\r
+                                       switch (against[i]) {\r
+                                               case 'd':\r
+                                               case 'e':\r
+                                                       d = parseInt(parts[i],10);\r
+                                                       break;\r
+                                               case 'm':\r
+                                                       m = parseInt(parts[i], 10)-1;\r
+                                                       break;\r
+                                               case 'Y':\r
+                                               case 'y':\r
+                                                       y = parseInt(parts[i], 10);\r
+                                                       y += y > 100 ? 0 : (y < 29 ? 2000 : 1900);\r
+                                                       break;\r
+                                               case 'H':\r
+                                               case 'I':\r
+                                               case 'k':\r
+                                               case 'l':\r
+                                                       h = parseInt(parts[i], 10);\r
+                                                       break;\r
+                                               case 'P':\r
+                                               case 'p':\r
+                                                       if (/pm/i.test(parts[i]) && h < 12) {\r
+                                                               h += 12;\r
+                                                       } else if (/am/i.test(parts[i]) && h >= 12) {\r
+                                                               h -= 12;\r
+                                                       }\r
+                                                       break;\r
+                                               case 'M':\r
+                                                       min = parseInt(parts[i], 10);\r
+                                                       break;\r
+                                       }\r
+                               }\r
+                               return new Date(\r
+                                       y === undefined ? now.getFullYear() : y,\r
+                                       m === undefined ? now.getMonth() : m,\r
+                                       d === undefined ? now.getDate() : d,\r
+                                       h === undefined ? now.getHours() : h,\r
+                                       min === undefined ? now.getMinutes() : min,\r
+                                       0\r
+                               );\r
+                       },\r
+                       formatDate = function(date, format) {\r
+                               var m = date.getMonth();\r
+                               var d = date.getDate();\r
+                               var y = date.getFullYear();\r
+                               var wn = date.getWeekNumber();\r
+                               var w = date.getDay();\r
+                               var s = {};\r
+                               var hr = date.getHours();\r
+                               var pm = (hr >= 12);\r
+                               var ir = (pm) ? (hr - 12) : hr;\r
+                               var dy = date.getDayOfYear();\r
+                               if (ir == 0) {\r
+                                       ir = 12;\r
+                               }\r
+                               var min = date.getMinutes();\r
+                               var sec = date.getSeconds();\r
+                               var parts = format.split(''), part;\r
+                               for ( var i = 0; i < parts.length; i++ ) {\r
+                                       part = parts[i];\r
+                                       switch (parts[i]) {\r
+                                               case 'a':\r
+                                                       part = date.getDayName();\r
+                                                       break;\r
+                                               case 'A':\r
+                                                       part = date.getDayName(true);\r
+                                                       break;\r
+                                               case 'b':\r
+                                                       part = date.getMonthName();\r
+                                                       break;\r
+                                               case 'B':\r
+                                                       part = date.getMonthName(true);\r
+                                                       break;\r
+                                               case 'C':\r
+                                                       part = 1 + Math.floor(y / 100);\r
+                                                       break;\r
+                                               case 'd':\r
+                                                       part = (d < 10) ? ("0" + d) : d;\r
+                                                       break;\r
+                                               case 'e':\r
+                                                       part = d;\r
+                                                       break;\r
+                                               case 'H':\r
+                                                       part = (hr < 10) ? ("0" + hr) : hr;\r
+                                                       break;\r
+                                               case 'I':\r
+                                                       part = (ir < 10) ? ("0" + ir) : ir;\r
+                                                       break;\r
+                                               case 'j':\r
+                                                       part = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy;\r
+                                                       break;\r
+                                               case 'k':\r
+                                                       part = hr;\r
+                                                       break;\r
+                                               case 'l':\r
+                                                       part = ir;\r
+                                                       break;\r
+                                               case 'm':\r
+                                                       part = (m < 9) ? ("0" + (1+m)) : (1+m);\r
+                                                       break;\r
+                                               case 'M':\r
+                                                       part = (min < 10) ? ("0" + min) : min;\r
+                                                       break;\r
+                                               case 'p':\r
+                                               case 'P':\r
+                                                       part = pm ? "PM" : "AM";\r
+                                                       break;\r
+                                               case 's':\r
+                                                       part = Math.floor(date.getTime() / 1000);\r
+                                                       break;\r
+                                               case 'S':\r
+                                                       part = (sec < 10) ? ("0" + sec) : sec;\r
+                                                       break;\r
+                                               case 'u':\r
+                                                       part = w + 1;\r
+                                                       break;\r
+                                               case 'w':\r
+                                                       part = w;\r
+                                                       break;\r
+                                               case 'y':\r
+                                                       part = ('' + y).substr(2, 2);\r
+                                                       break;\r
+                                               case 'Y':\r
+                                                       part = y;\r
+                                                       break;\r
+                                       }\r
+                                       parts[i] = part;\r
+                               }\r
+                               return parts.join('');\r
+                       },\r
+                       extendDate = function(options) {\r
+                               if (Date.prototype.tempDate) {\r
+                                       return;\r
+                               }\r
+                               Date.prototype.tempDate = null;\r
+                               Date.prototype.months = options.months;\r
+                               Date.prototype.monthsShort = options.monthsShort;\r
+                               Date.prototype.days = options.days;\r
+                               Date.prototype.daysShort = options.daysShort;\r
+                               Date.prototype.getMonthName = function(fullName) {\r
+                                       return this[fullName ? 'months' : 'monthsShort'][this.getMonth()];\r
+                               };\r
+                               Date.prototype.getDayName = function(fullName) {\r
+                                       return this[fullName ? 'days' : 'daysShort'][this.getDay()];\r
+                               };\r
+                               Date.prototype.addDays = function (n) {\r
+                                       this.setDate(this.getDate() + n);\r
+                                       this.tempDate = this.getDate();\r
+                               };\r
+                               Date.prototype.addMonths = function (n) {\r
+                                       if (this.tempDate == null) {\r
+                                               this.tempDate = this.getDate();\r
+                                       }\r
+                                       this.setDate(1);\r
+                                       this.setMonth(this.getMonth() + n);\r
+                                       this.setDate(Math.min(this.tempDate, this.getMaxDays()));\r
+                               };\r
+                               Date.prototype.addYears = function (n) {\r
+                                       if (this.tempDate == null) {\r
+                                               this.tempDate = this.getDate();\r
+                                       }\r
+                                       this.setDate(1);\r
+                                       this.setFullYear(this.getFullYear() + n);\r
+                                       this.setDate(Math.min(this.tempDate, this.getMaxDays()));\r
+                               };\r
+                               Date.prototype.getMaxDays = function() {\r
+                                       var tmpDate = new Date(Date.parse(this)),\r
+                                               d = 28, m;\r
+                                       m = tmpDate.getMonth();\r
+                                       d = 28;\r
+                                       while (tmpDate.getMonth() == m) {\r
+                                               d ++;\r
+                                               tmpDate.setDate(d);\r
+                                       }\r
+                                       return d - 1;\r
+                               };\r
+                               Date.prototype.getFirstDay = function() {\r
+                                       var tmpDate = new Date(Date.parse(this));\r
+                                       tmpDate.setDate(1);\r
+                                       return tmpDate.getDay();\r
+                               };\r
+                               Date.prototype.getWeekNumber = function() {\r
+                                       var tempDate = new Date(this);\r
+                                       tempDate.setDate(tempDate.getDate() - (tempDate.getDay() + 6) % 7 + 3);\r
+                                       var dms = tempDate.valueOf();\r
+                                       tempDate.setMonth(0);\r
+                                       tempDate.setDate(4);\r
+                                       return Math.round((dms - tempDate.valueOf()) / (604800000)) + 1;\r
+                               };\r
+                               Date.prototype.getDayOfYear = function() {\r
+                                       var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);\r
+                                       var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);\r
+                                       var time = now - then;\r
+                                       return Math.floor(time / 24*60*60*1000);\r
+                               };\r
+                       },\r
+                       layout = function (el) {\r
+                               var options = $(el).data('datepicker');\r
+                               var cal = $('#' + options.id);\r
+                               if (!options.extraHeight) {\r
+                                       var divs = $(el).find('div');\r
+                                       options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight;\r
+                                       options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth;\r
+                               }\r
+                               var tbl = cal.find('table:first').get(0);\r
+                               var width = tbl.offsetWidth;\r
+                               var height = tbl.offsetHeight;\r
+                               cal.css({\r
+                                       width: width + options.extraWidth + 'px',\r
+                                       height: height + options.extraHeight + 'px'\r
+                               }).find('div.datepickerContainer').css({\r
+                                       width: width + 'px',\r
+                                       height: height + 'px'\r
+                               });\r
+                       },\r
+                       click = function(ev) {\r
+                               if ($(ev.target).is('span')) {\r
+                                       ev.target = ev.target.parentNode;\r
+                               }\r
+                               var el = $(ev.target);\r
+                               if (el.is('a')) {\r
+                                       ev.target.blur();\r
+                                       if (el.hasClass('datepickerDisabled')) {\r
+                                               return false;\r
+                                       }\r
+                                       var options = $(this).data('datepicker');\r
+                                       var parentEl = el.parent();\r
+                                       var tblEl = parentEl.parent().parent().parent();\r
+                                       var tblIndex = $('table', this).index(tblEl.get(0)) - 1;\r
+                                       var tmp = new Date(options.current);\r
+                                       var changed = false;\r
+                                       var fillIt = false;\r
+                                       if (parentEl.is('th')) {\r
+                                               if (parentEl.hasClass('datepickerWeek') && options.mode == 'range' && !parentEl.next().hasClass('datepickerDisabled')) {\r
+                                                       var val = parseInt(parentEl.next().text(), 10);\r
+                                                       tmp.addMonths(tblIndex - Math.floor(options.calendars/2));\r
+                                                       if (parentEl.next().hasClass('datepickerNotInMonth')) {\r
+                                                               tmp.addMonths(val > 15 ? -1 : 1);\r
+                                                       }\r
+                                                       tmp.setDate(val);\r
+                                                       options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();\r
+                                                       tmp.setHours(23,59,59,0);\r
+                                                       tmp.addDays(6);\r
+                                                       options.date[1] = tmp.valueOf();\r
+                                                       fillIt = true;\r
+                                                       changed = true;\r
+                                                       options.lastSel = false;\r
+                                               } else if (parentEl.hasClass('datepickerMonth')) {\r
+                                                       tmp.addMonths(tblIndex - Math.floor(options.calendars/2));\r
+                                                       switch (tblEl.get(0).className) {\r
+                                                               case 'datepickerViewDays':\r
+                                                                       tblEl.get(0).className = 'datepickerViewMonths';\r
+                                                                       el.find('span').text(tmp.getFullYear());\r
+                                                                       break;\r
+                                                               case 'datepickerViewMonths':\r
+                                                                       tblEl.get(0).className = 'datepickerViewYears';\r
+                                                                       el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5));\r
+                                                                       break;\r
+                                                               case 'datepickerViewYears':\r
+                                                                       tblEl.get(0).className = 'datepickerViewDays';\r
+                                                                       el.find('span').text(formatDate(tmp, 'B, Y'));\r
+                                                                       break;\r
+                                                       }\r
+                                               } else if (parentEl.parent().parent().is('thead')) {\r
+                                                       switch (tblEl.get(0).className) {\r
+                                                               case 'datepickerViewDays':\r
+                                                                       options.current.addMonths(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);\r
+                                                                       break;\r
+                                                               case 'datepickerViewMonths':\r
+                                                                       options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -1 : 1);\r
+                                                                       break;\r
+                                                               case 'datepickerViewYears':\r
+                                                                       options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -12 : 12);\r
+                                                                       break;\r
+                                                       }\r
+                                                       fillIt = true;\r
+                                               }\r
+                                       } else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) {\r
+                                               switch (tblEl.get(0).className) {\r
+                                                       case 'datepickerViewMonths':\r
+                                                               options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl));\r
+                                                               options.current.setFullYear(parseInt(tblEl.find('thead th.datepickerMonth span').text(), 10));\r
+                                                               options.current.addMonths(Math.floor(options.calendars/2) - tblIndex);\r
+                                                               tblEl.get(0).className = 'datepickerViewDays';\r
+                                                               break;\r
+                                                       case 'datepickerViewYears':\r
+                                                               options.current.setFullYear(parseInt(el.text(), 10));\r
+                                                               tblEl.get(0).className = 'datepickerViewMonths';\r
+                                                               break;\r
+                                                       default:\r
+                                                               var val = parseInt(el.text(), 10);\r
+                                                               tmp.addMonths(tblIndex - Math.floor(options.calendars/2));\r
+                                                               if (parentEl.hasClass('datepickerNotInMonth')) {\r
+                                                                       tmp.addMonths(val > 15 ? -1 : 1);\r
+                                                               }\r
+                                                               tmp.setDate(val);\r
+                                                               switch (options.mode) {\r
+                                                                       case 'multiple':\r
+                                                                               val = (tmp.setHours(0,0,0,0)).valueOf();\r
+                                                                               if ($.inArray(val, options.date) > -1) {\r
+                                                                                       $.each(options.date, function(nr, dat){\r
+                                                                                               if (dat == val) {\r
+                                                                                                       options.date.splice(nr,1);\r
+                                                                                                       return false;\r
+                                                                                               }\r
+                                                                                       });\r
+                                                                               } else {\r
+                                                                                       options.date.push(val);\r
+                                                                               }\r
+                                                                               break;\r
+                                                                       case 'range':\r
+                                                                               if (!options.lastSel) {\r
+                                                                                       options.date[0] = (tmp.setHours(0,0,0,0)).valueOf();\r
+                                                                               }\r
+                                                                               val = (tmp.setHours(23,59,59,0)).valueOf();\r
+                                                                               if (val < options.date[0]) {\r
+                                                                                       options.date[1] = options.date[0] + 86399000;\r
+                                                                                       options.date[0] = val - 86399000;\r
+                                                                               } else {\r
+                                                                                       options.date[1] = val;\r
+                                                                               }\r
+                                                                               options.lastSel = !options.lastSel;\r
+                                                                               break;\r
+                                                                       default:\r
+                                                                               options.date = tmp.valueOf();\r
+                                                                               break;\r
+                                                               }\r
+                                                               break;\r
+                                               }\r
+                                               fillIt = true;\r
+                                               changed = true;\r
+                                       }\r
+                                       if (fillIt) {\r
+                                               fill(this);\r
+                                       }\r
+                                       if (changed) {\r
+                                               options.onChange.apply(this, prepareDate(options));\r
+                                       }\r
+                               }\r
+                               return false;\r
+                       },\r
+                       prepareDate = function (options) {\r
+                               var tmp;\r
+                               if (options.mode == 'single') {\r
+                                       tmp = new Date(options.date);\r
+                                       return [formatDate(tmp, options.format), tmp, options.el];\r
+                               } else {\r
+                                       tmp = [[],[], options.el];\r
+                                       $.each(options.date, function(nr, val){\r
+                                               var date = new Date(val);\r
+                                               tmp[0].push(formatDate(date, options.format));\r
+                                               tmp[1].push(date);\r
+                                       });\r
+                                       return tmp;\r
+                               }\r
+                       },\r
+                       getViewport = function () {\r
+                               var m = document.compatMode == 'CSS1Compat';\r
+                               return {\r
+                                       l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),\r
+                                       t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),\r
+                                       w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),\r
+                                       h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)\r
+                               };\r
+                       },\r
+                       isChildOf = function(parentEl, el, container) {\r
+                               if (parentEl == el) {\r
+                                       return true;\r
+                               }\r
+                               if (parentEl.contains) {\r
+                                       return parentEl.contains(el);\r
+                               }\r
+                               if ( parentEl.compareDocumentPosition ) {\r
+                                       return !!(parentEl.compareDocumentPosition(el) & 16);\r
+                               }\r
+                               var prEl = el.parentNode;\r
+                               while(prEl && prEl != container) {\r
+                                       if (prEl == parentEl)\r
+                                               return true;\r
+                                       prEl = prEl.parentNode;\r
+                               }\r
+                               return false;\r
+                       },\r
+                       show = function (ev) {\r
+                               var cal = $('#' + $(this).data('datepickerId'));\r
+                               if (!cal.is(':visible')) {\r
+                                       var calEl = cal.get(0);\r
+                                       fill(calEl);\r
+                                       var options = cal.data('datepicker');\r
+                                       options.onBeforeShow.apply(this, [cal.get(0)]);\r
+                                       var pos = $(this).offset();\r
+                                       var viewPort = getViewport();\r
+                                       var top = pos.top;\r
+                                       var left = pos.left;\r
+                                       var oldDisplay = $.curCSS(calEl, 'display');\r
+                                       cal.css({\r
+                                               visibility: 'hidden',\r
+                                               display: 'block'\r
+                                       });\r
+                                       layout(calEl);\r
+                                       switch (options.position){\r
+                                               case 'top':\r
+                                                       top -= calEl.offsetHeight;\r
+                                                       break;\r
+                                               case 'left':\r
+                                                       left -= calEl.offsetWidth;\r
+                                                       break;\r
+                                               case 'right':\r
+                                                       left += this.offsetWidth;\r
+                                                       break;\r
+                                               case 'bottom':\r
+                                                       top += this.offsetHeight;\r
+                                                       break;\r
+                                       }\r
+                                       if (top + calEl.offsetHeight > viewPort.t + viewPort.h) {\r
+                                               top = pos.top  - calEl.offsetHeight;\r
+                                       }\r
+                                       if (top < viewPort.t) {\r
+                                               top = pos.top + this.offsetHeight + calEl.offsetHeight;\r
+                                       }\r
+                                       if (left + calEl.offsetWidth > viewPort.l + viewPort.w) {\r
+                                               left = pos.left - calEl.offsetWidth;\r
+                                       }\r
+                                       if (left < viewPort.l) {\r
+                                               left = pos.left + this.offsetWidth\r
+                                       }\r
+                                       cal.css({\r
+                                               visibility: 'visible',\r
+                                               display: 'block',\r
+                                               top: top + 'px',\r
+                                               left: left + 'px'\r
+                                       });\r
+                                       if (options.onShow.apply(this, [cal.get(0)]) != false) {\r
+                                               cal.show();\r
+                                       }\r
+                                       $(document).bind('mousedown', {cal: cal, trigger: this}, hide);\r
+                               }\r
+                               return false;\r
+                       },\r
+                       hide = function (ev) {\r
+                               if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {\r
+                                       if (ev.data.cal.data('datepicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {\r
+                                               ev.data.cal.hide();\r
+                                       }\r
+                                       $(document).unbind('mousedown', hide);\r
+                               }\r
+                       };\r
+               return {\r
+                       init: function(options){\r
+                               options = $.extend({}, defaults, options||{});\r
+                               extendDate(options.locale);\r
+                               options.calendars = Math.max(1, parseInt(options.calendars,10)||1);\r
+                               options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single';\r
+                               return this.each(function(){\r
+                                       if (!$(this).data('datepicker')) {\r
+                                               options.el = this;\r
+                                               if (options.date.constructor == String) {\r
+                                                       options.date = parseDate(options.date, options.format);\r
+                                                       options.date.setHours(0,0,0,0);\r
+                                               }\r
+                                               if (options.mode != 'single') {\r
+                                                       if (options.date.constructor != Array) {\r
+                                                               options.date = [options.date.valueOf()];\r
+                                                               if (options.mode == 'range') {\r
+                                                                       options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());\r
+                                                               }\r
+                                                       } else {\r
+                                                               for (var i = 0; i < options.date.length; i++) {\r
+                                                                       options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();\r
+                                                               }\r
+                                                               if (options.mode == 'range') {\r
+                                                                       options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();\r
+                                                               }\r
+                                                       }\r
+                                               } else {\r
+                                                       options.date = options.date.valueOf();\r
+                                               }\r
+                                               if (!options.current) {\r
+                                                       options.current = new Date();\r
+                                               } else {\r
+                                                       options.current = parseDate(options.current, options.format);\r
+                                               } \r
+                                               options.current.setDate(1);\r
+                                               options.current.setHours(0,0,0,0);\r
+                                               var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt;\r
+                                               options.id = id;\r
+                                               $(this).data('datepickerId', options.id);\r
+                                               var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);\r
+                                               if (options.className) {\r
+                                                       cal.addClass(options.className);\r
+                                               }\r
+                                               var html = '';\r
+                                               for (var i = 0; i < options.calendars; i++) {\r
+                                                       cnt = options.starts;\r
+                                                       if (i > 0) {\r
+                                                               html += tpl.space;\r
+                                                       }\r
+                                                       html += tmpl(tpl.head.join(''), {\r
+                                                                       week: options.locale.weekMin,\r
+                                                                       prev: options.prev,\r
+                                                                       next: options.next,\r
+                                                                       day1: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day2: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day3: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day4: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day5: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day6: options.locale.daysMin[(cnt++)%7],\r
+                                                                       day7: options.locale.daysMin[(cnt++)%7]\r
+                                                               });\r
+                                               }\r
+                                               cal\r
+                                                       .find('tr:first').append(html)\r
+                                                               .find('table').addClass(views[options.view]);\r
+                                               fill(cal.get(0));\r
+                                               if (options.flat) {\r
+                                                       cal.appendTo(this).show().css('position', 'relative');\r
+                                                       layout(cal.get(0));\r
+                                               } else {\r
+                                                       cal.appendTo(document.body);\r
+                                                       $(this).bind(options.eventName, show);\r
+                                               }\r
+                                       }\r
+                               });\r
+                       },\r
+                       showPicker: function() {\r
+                               return this.each( function () {\r
+                                       if ($(this).data('datepickerId')) {\r
+                                               show.apply(this);\r
+                                       }\r
+                               });\r
+                       },\r
+                       hidePicker: function() {\r
+                               return this.each( function () {\r
+                                       if ($(this).data('datepickerId')) {\r
+                                               $('#' + $(this).data('datepickerId')).hide();\r
+                                       }\r
+                               });\r
+                       },\r
+                       setDate: function(date, shiftTo){\r
+                               return this.each(function(){\r
+                                       if ($(this).data('datepickerId')) {\r
+                                               var cal = $('#' + $(this).data('datepickerId'));\r
+                                               var options = cal.data('datepicker');\r
+                                               options.date = date;\r
+                                               if (options.date.constructor == String) {\r
+                                                       options.date = parseDate(options.date, options.format);\r
+                                                       options.date.setHours(0,0,0,0);\r
+                                               }\r
+                                               if (options.mode != 'single') {\r
+                                                       if (options.date.constructor != Array) {\r
+                                                               options.date = [options.date.valueOf()];\r
+                                                               if (options.mode == 'range') {\r
+                                                                       options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf());\r
+                                                               }\r
+                                                       } else {\r
+                                                               for (var i = 0; i < options.date.length; i++) {\r
+                                                                       options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf();\r
+                                                               }\r
+                                                               if (options.mode == 'range') {\r
+                                                                       options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf();\r
+                                                               }\r
+                                                       }\r
+                                               } else {\r
+                                                       options.date = options.date.valueOf();\r
+                                               }\r
+                                               if (shiftTo) {\r
+                                                       options.current = new Date (options.mode != 'single' ? options.date[0] : options.date);\r
+                                               }\r
+                                               fill(cal.get(0));\r
+                                       }\r
+                               });\r
+                       },\r
+                       getDate: function(formated) {\r
+                               if (this.size() > 0) {\r
+                                       return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'))[formated ? 0 : 1];\r
+                               }\r
+                       },\r
+                       clear: function(){\r
+                               return this.each(function(){\r
+                                       if ($(this).data('datepickerId')) {\r
+                                               var cal = $('#' + $(this).data('datepickerId'));\r
+                                               var options = cal.data('datepicker');\r
+                                               if (options.mode != 'single') {\r
+                                                       options.date = [];\r
+                                                       fill(cal.get(0));\r
+                                               }\r
+                                       }\r
+                               });\r
+                       },\r
+                       fixLayout: function(){\r
+                               return this.each(function(){\r
+                                       if ($(this).data('datepickerId')) {\r
+                                               var cal = $('#' + $(this).data('datepickerId'));\r
+                                               var options = cal.data('datepicker');\r
+                                               if (options.flat) {\r
+                                                       layout(cal.get(0));\r
+                                               }\r
+                                       }\r
+                               });\r
+                       }\r
+               };\r
+       }();\r
+       $.fn.extend({\r
+               DatePicker: DatePicker.init,\r
+               DatePickerHide: DatePicker.hidePicker,\r
+               DatePickerShow: DatePicker.showPicker,\r
+               DatePickerSetDate: DatePicker.setDate,\r
+               DatePickerGetDate: DatePicker.getDate,\r
+               DatePickerClear: DatePicker.clear,\r
+               DatePickerLayout: DatePicker.fixLayout\r
+       });\r
+})(jQuery);\r
+\r
+(function(){\r
+  var cache = {};\r
\r
+  this.tmpl = function tmpl(str, data){\r
+    // Figure out if we're getting a template, or if we need to\r
+    // load the template - and be sure to cache the result.\r
+    var fn = !/\W/.test(str) ?\r
+      cache[str] = cache[str] ||\r
+        tmpl(document.getElementById(str).innerHTML) :\r
+     \r
+      // Generate a reusable function that will serve as a template\r
+      // generator (and which will be cached).\r
+      new Function("obj",\r
+        "var p=[],print=function(){p.push.apply(p,arguments);};" +\r
+       \r
+        // Introduce the data as local variables using with(){}\r
+        "with(obj){p.push('" +\r
+       \r
+        // Convert the template into pure JavaScript\r
+        str\r
+          .replace(/[\r\t\n]/g, " ")\r
+          .split("<%").join("\t")\r
+          .replace(/((^|%>)[^\t]*)'/g, "$1\r")\r
+          .replace(/\t=(.*?)%>/g, "',$1,'")\r
+          .split("\t").join("');")\r
+          .split("%>").join("p.push('")\r
+          .split("\r").join("\\'")\r
+      + "');}return p.join('');");\r
+   \r
+    // Provide some basic currying to the user\r
+    return data ? fn( data ) : fn;\r
+  };\r
+})();\r
diff --git a/jappixmini/jappix/js/jquery.form.js b/jappixmini/jappix/js/jquery.form.js
new file mode 100644 (file)
index 0000000..2b853df
--- /dev/null
@@ -0,0 +1,785 @@
+/*!
+ * jQuery Form Plugin
+ * version: 2.49 (18-OCT-2010)
+ * @requires jQuery v1.3.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ */
+;(function($) {
+
+/*
+       Usage Note:
+       -----------
+       Do not use both ajaxSubmit and ajaxForm on the same form.  These
+       functions are intended to be exclusive.  Use ajaxSubmit if you want
+       to bind your own submit handler to the form.  For example,
+
+       $(document).ready(function() {
+               $('#myForm').bind('submit', function(e) {
+                       e.preventDefault(); // <-- important
+                       $(this).ajaxSubmit({
+                               target: '#output'
+                       });
+               });
+       });
+
+       Use ajaxForm when you want the plugin to manage all the event binding
+       for you.  For example,
+
+       $(document).ready(function() {
+               $('#myForm').ajaxForm({
+                       target: '#output'
+               });
+       });
+
+       When using ajaxForm, the ajaxSubmit function will be invoked for you
+       at the appropriate time.
+*/
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+       // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+       if (!this.length) {
+               log('ajaxSubmit: skipping submit process - no element selected');
+               return this;
+       }
+
+       if (typeof options == 'function') {
+               options = { success: options };
+       }
+
+       var url = $.trim(this.attr('action'));
+       if (url) {
+               // clean url (don't include hash vaue)
+               url = (url.match(/^([^#]+)/)||[])[1];
+       }
+       url = url || window.location.href || '';
+
+       options = $.extend(true, {
+               url:  url,
+               type: this.attr('method') || 'GET',
+               iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
+       }, options);
+
+       // hook for manipulating the form data before it is extracted;
+       // convenient for use with rich editors like tinyMCE or FCKEditor
+       var veto = {};
+       this.trigger('form-pre-serialize', [this, options, veto]);
+       if (veto.veto) {
+               log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+               return this;
+       }
+
+       // provide opportunity to alter form data before it is serialized
+       if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+               log('ajaxSubmit: submit aborted via beforeSerialize callback');
+               return this;
+       }
+
+       var n,v,a = this.formToArray(options.semantic);
+       if (options.data) {
+               options.extraData = options.data;
+               for (n in options.data) {
+                       if(options.data[n] instanceof Array) {
+                               for (var k in options.data[n]) {
+                                       a.push( { name: n, value: options.data[n][k] } );
+                               }
+                       }
+                       else {
+                               v = options.data[n];
+                               v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
+                               a.push( { name: n, value: v } );
+                       }
+               }
+       }
+
+       // give pre-submit callback an opportunity to abort the submit
+       if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+               log('ajaxSubmit: submit aborted via beforeSubmit callback');
+               return this;
+       }
+
+       // fire vetoable 'validate' event
+       this.trigger('form-submit-validate', [a, this, options, veto]);
+       if (veto.veto) {
+               log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+               return this;
+       }
+
+       var q = $.param(a);
+
+       if (options.type.toUpperCase() == 'GET') {
+               options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+               options.data = null;  // data is null for 'get'
+       }
+       else {
+               options.data = q; // data is the query string for 'post'
+       }
+
+       var $form = this, callbacks = [];
+       if (options.resetForm) {
+               callbacks.push(function() { $form.resetForm(); });
+       }
+       if (options.clearForm) {
+               callbacks.push(function() { $form.clearForm(); });
+       }
+
+       // perform a load on the target only if dataType is not provided
+       if (!options.dataType && options.target) {
+               var oldSuccess = options.success || function(){};
+               callbacks.push(function(data) {
+                       var fn = options.replaceTarget ? 'replaceWith' : 'html';
+                       $(options.target)[fn](data).each(oldSuccess, arguments);
+               });
+       }
+       else if (options.success) {
+               callbacks.push(options.success);
+       }
+
+       options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
+               var context = options.context || options;   // jQuery 1.4+ supports scope context 
+               for (var i=0, max=callbacks.length; i < max; i++) {
+                       callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+               }
+       };
+
+       // are there files to upload?
+       var fileInputs = $('input:file', this).length > 0;
+       var mp = 'multipart/form-data';
+       var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+       // options.iframe allows user to force iframe mode
+       // 06-NOV-09: now defaulting to iframe mode if file input is detected
+   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
+          // hack to fix Safari hang (thanks to Tim Molendijk for this)
+          // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+          if (options.closeKeepAlive) {
+                  $.get(options.closeKeepAlive, fileUpload);
+               }
+          else {
+                  fileUpload();
+               }
+   }
+   else {
+          $.ajax(options);
+   }
+
+       // fire 'notify' event
+       this.trigger('form-submit-notify', [this, options]);
+       return this;
+
+
+       // private function for handling file uploads (hat tip to YAHOO!)
+       function fileUpload() {
+               var form = $form[0];
+
+               if ($(':input[name=submit],:input[id=submit]', form).length) {
+                       // if there is an input with a name or id of 'submit' then we won't be
+                       // able to invoke the submit fn on the form (at least not x-browser)
+                       alert('Error: Form elements must not have name or id of "submit".');
+                       return;
+               }
+               
+               var s = $.extend(true, {}, $.ajaxSettings, options);
+               s.context = s.context || s;
+               var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
+               window[fn] = function() {
+                       var f = $io.data('form-plugin-onload');
+                       if (f) {
+                               f();
+                               window[fn] = undefined;
+                               try { delete window[fn]; } catch(e){}
+                       }
+               }
+               var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
+               var io = $io[0];
+
+               $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+
+               var xhr = { // mock object
+                       aborted: 0,
+                       responseText: null,
+                       responseXML: null,
+                       status: 0,
+                       statusText: 'n/a',
+                       getAllResponseHeaders: function() {},
+                       getResponseHeader: function() {},
+                       setRequestHeader: function() {},
+                       abort: function() {
+                               this.aborted = 1;
+                               $io.attr('src', s.iframeSrc); // abort op in progress
+                       }
+               };
+
+               var g = s.global;
+               // trigger ajax global events so that activity/block indicators work like normal
+               if (g && ! $.active++) {
+                       $.event.trigger("ajaxStart");
+               }
+               if (g) {
+                       $.event.trigger("ajaxSend", [xhr, s]);
+               }
+
+               if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+                       if (s.global) { 
+                               $.active--;
+                       }
+                       return;
+               }
+               if (xhr.aborted) {
+                       return;
+               }
+
+               var cbInvoked = false;
+               var timedOut = 0;
+
+               // add submitting element to data if we know it
+               var sub = form.clk;
+               if (sub) {
+                       var n = sub.name;
+                       if (n && !sub.disabled) {
+                               s.extraData = s.extraData || {};
+                               s.extraData[n] = sub.value;
+                               if (sub.type == "image") {
+                                       s.extraData[n+'.x'] = form.clk_x;
+                                       s.extraData[n+'.y'] = form.clk_y;
+                               }
+                       }
+               }
+
+               // take a breath so that pending repaints get some cpu time before the upload starts
+               function doSubmit() {
+                       // make sure form attrs are set
+                       var t = $form.attr('target'), a = $form.attr('action');
+
+                       // update form attrs in IE friendly way
+                       form.setAttribute('target',id);
+                       if (form.getAttribute('method') != 'POST') {
+                               form.setAttribute('method', 'POST');
+                       }
+                       if (form.getAttribute('action') != s.url) {
+                               form.setAttribute('action', s.url);
+                       }
+
+                       // ie borks in some cases when setting encoding
+                       if (! s.skipEncodingOverride) {
+                               $form.attr({
+                                       encoding: 'multipart/form-data',
+                                       enctype:  'multipart/form-data'
+                               });
+                       }
+
+                       // support timout
+                       if (s.timeout) {
+                               setTimeout(function() { timedOut = true; cb(); }, s.timeout);
+                       }
+
+                       // add "extra" data to form if provided in options
+                       var extraInputs = [];
+                       try {
+                               if (s.extraData) {
+                                       for (var n in s.extraData) {
+                                               extraInputs.push(
+                                                       $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
+                                                               .appendTo(form)[0]);
+                                       }
+                               }
+
+                               // add iframe to doc and submit the form
+                               $io.appendTo('body');
+                               $io.data('form-plugin-onload', cb);
+                               form.submit();
+                       }
+                       finally {
+                               // reset attrs and remove "extra" input elements
+                               form.setAttribute('action',a);
+                               if(t) {
+                                       form.setAttribute('target', t);
+                               } else {
+                                       $form.removeAttr('target');
+                               }
+                               $(extraInputs).remove();
+                       }
+               }
+
+               if (s.forceSync) {
+                       doSubmit();
+               }
+               else {
+                       setTimeout(doSubmit, 10); // this lets dom updates render
+               }
+       
+               var data, doc, domCheckCount = 50;
+
+               function cb() {
+                       if (cbInvoked) {
+                               return;
+                       }
+
+                       $io.removeData('form-plugin-onload');
+                       
+                       var ok = true;
+                       try {
+                               if (timedOut) {
+                                       throw 'timeout';
+                               }
+                               // extract the server response from the iframe
+                               doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
+                               
+                               var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+                               log('isXml='+isXml);
+                               if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
+                                       if (--domCheckCount) {
+                                               // in some browsers (Opera) the iframe DOM is not always traversable when
+                                               // the onload callback fires, so we loop a bit to accommodate
+                                               log('requeing onLoad callback, DOM not available');
+                                               setTimeout(cb, 250);
+                                               return;
+                                       }
+                                       // let this fall through because server response could be an empty document
+                                       //log('Could not access iframe DOM after mutiple tries.');
+                                       //throw 'DOMException: not available';
+                               }
+
+                               //log('response detected');
+                               cbInvoked = true;
+                               xhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null; 
+                               xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+                               xhr.getResponseHeader = function(header){
+                                       var headers = {'content-type': s.dataType};
+                                       return headers[header];
+                               };
+
+                               var scr = /(json|script)/.test(s.dataType);
+                               if (scr || s.textarea) {
+                                       // see if user embedded response in textarea
+                                       var ta = doc.getElementsByTagName('textarea')[0];
+                                       if (ta) {
+                                               xhr.responseText = ta.value;
+                                       }
+                                       else if (scr) {
+                                               // account for browsers injecting pre around json response
+                                               var pre = doc.getElementsByTagName('pre')[0];
+                                               var b = doc.getElementsByTagName('body')[0];
+                                               if (pre) {
+                                                       xhr.responseText = pre.innerHTML;
+                                               }
+                                               else if (b) {
+                                                       xhr.responseText = b.innerHTML;
+                                               }
+                                       }                         
+                               }
+                               else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
+                                       xhr.responseXML = toXml(xhr.responseText);
+                               }
+                               data = $.httpData(xhr, s.dataType);
+                       }
+                       catch(e){
+                               log('error caught:',e);
+                               ok = false;
+                               xhr.error = e;
+                               $.handleError(s, xhr, 'error', e);
+                       }
+
+                       // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+                       if (ok) {
+                               s.success.call(s.context, data, 'success', xhr);
+                               if (g) {
+                                       $.event.trigger("ajaxSuccess", [xhr, s]);
+                               }
+                       }
+                       if (g) {
+                               $.event.trigger("ajaxComplete", [xhr, s]);
+                       }
+                       if (g && ! --$.active) {
+                               $.event.trigger("ajaxStop");
+                       }
+                       if (s.complete) {
+                               s.complete.call(s.context, xhr, ok ? 'success' : 'error');
+                       }
+
+                       // clean up
+                       setTimeout(function() {
+                               $io.removeData('form-plugin-onload');
+                               $io.remove();
+                               xhr.responseXML = null;
+                       }, 100);
+               }
+
+               function toXml(s, doc) {
+                       if (window.ActiveXObject) {
+                               doc = new ActiveXObject('Microsoft.XMLDOM');
+                               doc.async = 'false';
+                               doc.loadXML(s);
+                       }
+                       else {
+                               doc = (new DOMParser()).parseFromString(s, 'text/xml');
+                       }
+                       return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
+               }
+       }
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ *     is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ *     used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+       // in jQuery 1.3+ we can fix mistakes with the ready state
+       if (this.length === 0) {
+               var o = { s: this.selector, c: this.context };
+               if (!$.isReady && o.s) {
+                       log('DOM not ready, queuing ajaxForm');
+                       $(function() {
+                               $(o.s,o.c).ajaxForm(options);
+                       });
+                       return this;
+               }
+               // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+               log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+               return this;
+       }
+       
+       return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
+               if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
+                       e.preventDefault();
+                       $(this).ajaxSubmit(options);
+               }
+       }).bind('click.form-plugin', function(e) {
+               var target = e.target;
+               var $el = $(target);
+               if (!($el.is(":submit,input:image"))) {
+                       // is this a child element of the submit el?  (ex: a span within a button)
+                       var t = $el.closest(':submit');
+                       if (t.length == 0) {
+                               return;
+                       }
+                       target = t[0];
+               }
+               var form = this;
+               form.clk = target;
+               if (target.type == 'image') {
+                       if (e.offsetX != undefined) {
+                               form.clk_x = e.offsetX;
+                               form.clk_y = e.offsetY;
+                       } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
+                               var offset = $el.offset();
+                               form.clk_x = e.pageX - offset.left;
+                               form.clk_y = e.pageY - offset.top;
+                       } else {
+                               form.clk_x = e.pageX - target.offsetLeft;
+                               form.clk_y = e.pageY - target.offsetTop;
+                       }
+               }
+               // clear form vars
+               setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
+       });
+};
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+       return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property.  An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic) {
+       var a = [];
+       if (this.length === 0) {
+               return a;
+       }
+
+       var form = this[0];
+       var els = semantic ? form.getElementsByTagName('*') : form.elements;
+       if (!els) {
+               return a;
+       }
+       
+       var i,j,n,v,el,max,jmax;
+       for(i=0, max=els.length; i < max; i++) {
+               el = els[i];
+               n = el.name;
+               if (!n) {
+                       continue;
+               }
+
+               if (semantic && form.clk && el.type == "image") {
+                       // handle image inputs on the fly when semantic == true
+                       if(!el.disabled && form.clk == el) {
+                               a.push({name: n, value: $(el).val()});
+                               a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+                       }
+                       continue;
+               }
+
+               v = $.fieldValue(el, true);
+               if (v && v.constructor == Array) {
+                       for(j=0, jmax=v.length; j < jmax; j++) {
+                               a.push({name: n, value: v[j]});
+                       }
+               }
+               else if (v !== null && typeof v != 'undefined') {
+                       a.push({name: n, value: v});
+               }
+       }
+
+       if (!semantic && form.clk) {
+               // input type=='image' are not found in elements array! handle it here
+               var $input = $(form.clk), input = $input[0];
+               n = input.name;
+               if (n && !input.disabled && input.type == 'image') {
+                       a.push({name: n, value: $input.val()});
+                       a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+               }
+       }
+       return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+       //hand off to jQuery.param for proper encoding
+       return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+       var a = [];
+       this.each(function() {
+               var n = this.name;
+               if (!n) {
+                       return;
+               }
+               var v = $.fieldValue(this, successful);
+               if (v && v.constructor == Array) {
+                       for (var i=0,max=v.length; i < max; i++) {
+                               a.push({name: n, value: v[i]});
+                       }
+               }
+               else if (v !== null && typeof v != 'undefined') {
+                       a.push({name: this.name, value: v});
+               }
+       });
+       //hand off to jQuery.param for proper encoding
+       return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set.  For example, consider the following form:
+ *
+ *  <form><fieldset>
+ *       <input name="A" type="text" />
+ *       <input name="A" type="text" />
+ *       <input name="B" type="checkbox" value="B1" />
+ *       <input name="B" type="checkbox" value="B2"/>
+ *       <input name="C" type="radio" value="C1" />
+ *       <input name="C" type="radio" value="C2" />
+ *  </fieldset></form>
+ *
+ *  var v = $(':text').fieldValue();
+ *  // if no values are entered into the text inputs
+ *  v == ['','']
+ *  // if values entered into the text inputs are 'foo' and 'bar'
+ *  v == ['foo','bar']
+ *
+ *  var v = $(':checkbox').fieldValue();
+ *  // if neither checkbox is checked
+ *  v === undefined
+ *  // if both checkboxes are checked
+ *  v == ['B1', 'B2']
+ *
+ *  var v = $(':radio').fieldValue();
+ *  // if neither radio is checked
+ *  v === undefined
+ *  // if first radio is checked
+ *  v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true.  If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array.  If no valid value can be determined the
+ *        array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+       for (var val=[], i=0, max=this.length; i < max; i++) {
+               var el = this[i];
+               var v = $.fieldValue(el, successful);
+               if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
+                       continue;
+               }
+               v.constructor == Array ? $.merge(val, v) : val.push(v);
+       }
+       return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+       var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+       if (successful === undefined) {
+               successful = true;
+       }
+
+       if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+               (t == 'checkbox' || t == 'radio') && !el.checked ||
+               (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+               tag == 'select' && el.selectedIndex == -1)) {
+                       return null;
+       }
+
+       if (tag == 'select') {
+               var index = el.selectedIndex;
+               if (index < 0) {
+                       return null;
+               }
+               var a = [], ops = el.options;
+               var one = (t == 'select-one');
+               var max = (one ? index+1 : ops.length);
+               for(var i=(one ? index : 0); i < max; i++) {
+                       var op = ops[i];
+                       if (op.selected) {
+                               var v = op.value;
+                               if (!v) { // extra pain for IE...
+                                       v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+                               }
+                               if (one) {
+                                       return v;
+                               }
+                               a.push(v);
+                       }
+               }
+               return a;
+       }
+       return $(el).val();
+};
+
+/**
+ * Clears the form data.  Takes the following actions on the form's input fields:
+ *  - input text fields will have their 'value' property set to the empty string
+ *  - select elements will have their 'selectedIndex' property set to -1
+ *  - checkbox and radio inputs will have their 'checked' property set to false
+ *  - inputs of type submit, button, reset, and hidden will *not* be effected
+ *  - button elements will *not* be effected
+ */
+$.fn.clearForm = function() {
+       return this.each(function() {
+               $('input,select,textarea', this).clearFields();
+       });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function() {
+       return this.each(function() {
+               var t = this.type, tag = this.tagName.toLowerCase();
+               if (t == 'text' || t == 'password' || tag == 'textarea') {
+                       this.value = '';
+               }
+               else if (t == 'checkbox' || t == 'radio') {
+                       this.checked = false;
+               }
+               else if (tag == 'select') {
+                       this.selectedIndex = -1;
+               }
+       });
+};
+
+/**
+ * Resets the form data.  Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+       return this.each(function() {
+               // guard against an input with the name of 'reset'
+               // note that IE reports the reset function as an 'object'
+               if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
+                       this.reset();
+               }
+       });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+       if (b === undefined) {
+               b = true;
+       }
+       return this.each(function() {
+               this.disabled = !b;
+       });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+       if (select === undefined) {
+               select = true;
+       }
+       return this.each(function() {
+               var t = this.type;
+               if (t == 'checkbox' || t == 'radio') {
+                       this.checked = select;
+               }
+               else if (this.tagName.toLowerCase() == 'option') {
+                       var $sel = $(this).parent('select');
+                       if (select && $sel[0] && $sel[0].type == 'select-one') {
+                               // deselect all other options
+                               $sel.find('option').selected(false);
+                       }
+                       this.selected = select;
+               }
+       });
+};
+
+// helper fn for console logging
+// set $.fn.ajaxSubmit.debug to true to enable debug logging
+function log() {
+       if ($.fn.ajaxSubmit.debug) {
+               var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+               if (window.console && window.console.log) {
+                       window.console.log(msg);
+               }
+               else if (window.opera && window.opera.postError) {
+                       window.opera.postError(msg);
+               }
+       }
+};
+
+})(jQuery);
diff --git a/jappixmini/jappix/js/jquery.js b/jappixmini/jappix/js/jquery.js
new file mode 100644 (file)
index 0000000..a4f1145
--- /dev/null
@@ -0,0 +1,7179 @@
+/*!
+ * jQuery JavaScript Library v1.4.4
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 11 19:04:53 2010 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return new jQuery.fn.init( selector, context );
+       },
+
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+
+       // Map over the $ in case of overwrite
+       _$ = window.$,
+
+       // A central reference to the root jQuery(document)
+       rootjQuery,
+
+       // A simple way to check for HTML strings or ID strings
+       // (both of which we optimize for)
+       quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
+
+       // Is it a simple selector
+       isSimple = /^.[^:#\[\.,]*$/,
+
+       // Check if a string has a non-whitespace character in it
+       rnotwhite = /\S/,
+       rwhite = /\s/,
+
+       // Used for trimming whitespace
+       trimLeft = /^\s+/,
+       trimRight = /\s+$/,
+
+       // Check for non-word characters
+       rnonword = /\W/,
+
+       // Check for digits
+       rdigit = /\d/,
+
+       // Match a standalone tag
+       rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+       // JSON RegExp
+       rvalidchars = /^[\],:{}\s]*$/,
+       rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+       rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+       rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+       // Useragent RegExp
+       rwebkit = /(webkit)[ \/]([\w.]+)/,
+       ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+       rmsie = /(msie) ([\w.]+)/,
+       rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+       // Keep a UserAgent string for use with jQuery.browser
+       userAgent = navigator.userAgent,
+
+       // For matching the engine and version of the browser
+       browserMatch,
+       
+       // Has the ready events already been bound?
+       readyBound = false,
+       
+       // The functions to execute on DOM ready
+       readyList = [],
+
+       // The ready event handler
+       DOMContentLoaded,
+
+       // Save a reference to some core methods
+       toString = Object.prototype.toString,
+       hasOwn = Object.prototype.hasOwnProperty,
+       push = Array.prototype.push,
+       slice = Array.prototype.slice,
+       trim = String.prototype.trim,
+       indexOf = Array.prototype.indexOf,
+       
+       // [[Class]] -> type pairs
+       class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+       init: function( selector, context ) {
+               var match, elem, ret, doc;
+
+               // Handle $(""), $(null), or $(undefined)
+               if ( !selector ) {
+                       return this;
+               }
+
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this.context = this[0] = selector;
+                       this.length = 1;
+                       return this;
+               }
+               
+               // The body element only exists once, optimize finding it
+               if ( selector === "body" && !context && document.body ) {
+                       this.context = document;
+                       this[0] = document.body;
+                       this.selector = "body";
+                       this.length = 1;
+                       return this;
+               }
+
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       // Are we dealing with HTML string or an ID?
+                       match = quickExpr.exec( selector );
+
+                       // Verify a match, and that no context was specified for #id
+                       if ( match && (match[1] || !context) ) {
+
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] ) {
+                                       doc = (context ? context.ownerDocument || context : document);
+
+                                       // If a single string is passed in and it's a single tag
+                                       // just do a createElement and skip the rest
+                                       ret = rsingleTag.exec( selector );
+
+                                       if ( ret ) {
+                                               if ( jQuery.isPlainObject( context ) ) {
+                                                       selector = [ document.createElement( ret[1] ) ];
+                                                       jQuery.fn.attr.call( selector, context, true );
+
+                                               } else {
+                                                       selector = [ doc.createElement( ret[1] ) ];
+                                               }
+
+                                       } else {
+                                               ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+                                               selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+                                       }
+                                       
+                                       return jQuery.merge( this, selector );
+                                       
+                               // HANDLE: $("#id")
+                               } else {
+                                       elem = document.getElementById( match[2] );
+
+                                       // Check parentNode to catch when Blackberry 4.6 returns
+                                       // nodes that are no longer in the document #6963
+                                       if ( elem && elem.parentNode ) {
+                                               // Handle the case where IE and Opera return items
+                                               // by name instead of ID
+                                               if ( elem.id !== match[2] ) {
+                                                       return rootjQuery.find( selector );
+                                               }
+
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               this.length = 1;
+                                               this[0] = elem;
+                                       }
+
+                                       this.context = document;
+                                       this.selector = selector;
+                                       return this;
+                               }
+
+                       // HANDLE: $("TAG")
+                       } else if ( !context && !rnonword.test( selector ) ) {
+                               this.selector = selector;
+                               this.context = document;
+                               selector = document.getElementsByTagName( selector );
+                               return jQuery.merge( this, selector );
+
+                       // HANDLE: $(expr, $(...))
+                       } else if ( !context || context.jquery ) {
+                               return (context || rootjQuery).find( selector );
+
+                       // HANDLE: $(expr, context)
+                       // (which is just equivalent to: $(context).find(expr)
+                       } else {
+                               return jQuery( context ).find( selector );
+                       }
+
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) ) {
+                       return rootjQuery.ready( selector );
+               }
+
+               if (selector.selector !== undefined) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
+               }
+
+               return jQuery.makeArray( selector, this );
+       },
+
+       // Start with an empty selector
+       selector: "",
+
+       // The current version of jQuery being used
+       jquery: "1.4.4",
+
+       // The default length of a jQuery object is 0
+       length: 0,
+
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+
+       toArray: function() {
+               return slice.call( this, 0 );
+       },
+
+       // Get the Nth element in the matched element set OR
+       // Get the whole matched element set as a clean array
+       get: function( num ) {
+               return num == null ?
+
+                       // Return a 'clean' array
+                       this.toArray() :
+
+                       // Return just the object
+                       ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
+       },
+
+       // Take an array of elements and push it onto the stack
+       // (returning the new matched element set)
+       pushStack: function( elems, name, selector ) {
+               // Build a new jQuery matched element set
+               var ret = jQuery();
+
+               if ( jQuery.isArray( elems ) ) {
+                       push.apply( ret, elems );
+               
+               } else {
+                       jQuery.merge( ret, elems );
+               }
+
+               // Add the old object onto the stack (as a reference)
+               ret.prevObject = this;
+
+               ret.context = this.context;
+
+               if ( name === "find" ) {
+                       ret.selector = this.selector + (this.selector ? " " : "") + selector;
+               } else if ( name ) {
+                       ret.selector = this.selector + "." + name + "(" + selector + ")";
+               }
+
+               // Return the newly-formed element set
+               return ret;
+       },
+
+       // Execute a callback for every element in the matched set.
+       // (You can seed the arguments with an array of args, but this is
+       // only used internally.)
+       each: function( callback, args ) {
+               return jQuery.each( this, callback, args );
+       },
+       
+       ready: function( fn ) {
+               // Attach the listeners
+               jQuery.bindReady();
+
+               // If the DOM is already ready
+               if ( jQuery.isReady ) {
+                       // Execute the function immediately
+                       fn.call( document, jQuery );
+
+               // Otherwise, remember the function for later
+               } else if ( readyList ) {
+                       // Add the function to the wait list
+                       readyList.push( fn );
+               }
+
+               return this;
+       },
+       
+       eq: function( i ) {
+               return i === -1 ?
+                       this.slice( i ) :
+                       this.slice( i, +i + 1 );
+       },
+
+       first: function() {
+               return this.eq( 0 );
+       },
+
+       last: function() {
+               return this.eq( -1 );
+       },
+
+       slice: function() {
+               return this.pushStack( slice.apply( this, arguments ),
+                       "slice", slice.call(arguments).join(",") );
+       },
+
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function( elem, i ) {
+                       return callback.call( elem, i, elem );
+               }));
+       },
+       
+       end: function() {
+               return this.prevObject || jQuery(null);
+       },
+
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: push,
+       sort: [].sort,
+       splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+        var options, name, src, copy, copyIsArray, clone,
+               target = arguments[0] || {},
+               i = 1,
+               length = arguments.length,
+               deep = false;
+
+       // Handle a deep copy situation
+       if ( typeof target === "boolean" ) {
+               deep = target;
+               target = arguments[1] || {};
+               // skip the boolean and the target
+               i = 2;
+       }
+
+       // Handle case when target is a string or something (possible in deep copy)
+       if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+               target = {};
+       }
+
+       // extend jQuery itself if only one argument is passed
+       if ( length === i ) {
+               target = this;
+               --i;
+       }
+
+       for ( ; i < length; i++ ) {
+               // Only deal with non-null/undefined values
+               if ( (options = arguments[ i ]) != null ) {
+                       // Extend the base object
+                       for ( name in options ) {
+                               src = target[ name ];
+                               copy = options[ name ];
+
+                               // Prevent never-ending loop
+                               if ( target === copy ) {
+                                       continue;
+                               }
+
+                               // Recurse if we're merging plain objects or arrays
+                               if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+                                       if ( copyIsArray ) {
+                                               copyIsArray = false;
+                                               clone = src && jQuery.isArray(src) ? src : [];
+
+                                       } else {
+                                               clone = src && jQuery.isPlainObject(src) ? src : {};
+                                       }
+
+                                       // Never move original objects, clone them
+                                       target[ name ] = jQuery.extend( deep, clone, copy );
+
+                               // Don't bring in undefined values
+                               } else if ( copy !== undefined ) {
+                                       target[ name ] = copy;
+                               }
+                       }
+               }
+       }
+
+       // Return the modified object
+       return target;
+};
+
+jQuery.extend({
+       noConflict: function( deep ) {
+               window.$ = _$;
+
+               if ( deep ) {
+                       window.jQuery = _jQuery;
+               }
+
+               return jQuery;
+       },
+       
+       // Is the DOM ready to be used? Set to true once it occurs.
+       isReady: false,
+
+       // A counter to track how many items to wait for before
+       // the ready event fires. See #6781
+       readyWait: 1,
+       
+       // Handle when the DOM is ready
+       ready: function( wait ) {
+               // A third-party is pushing the ready event forwards
+               if ( wait === true ) {
+                       jQuery.readyWait--;
+               }
+
+               // Make sure that the DOM is not already loaded
+               if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
+                       // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+                       if ( !document.body ) {
+                               return setTimeout( jQuery.ready, 1 );
+                       }
+
+                       // Remember that the DOM is ready
+                       jQuery.isReady = true;
+
+                       // If a normal DOM Ready event fired, decrement, and wait if need be
+                       if ( wait !== true && --jQuery.readyWait > 0 ) {
+                               return;
+                       }
+
+                       // If there are functions bound, to execute
+                       if ( readyList ) {
+                               // Execute all of them
+                               var fn,
+                                       i = 0,
+                                       ready = readyList;
+
+                               // Reset the list of functions
+                               readyList = null;
+
+                               while ( (fn = ready[ i++ ]) ) {
+                                       fn.call( document, jQuery );
+                               }
+
+                               // Trigger any bound ready events
+                               if ( jQuery.fn.trigger ) {
+                                       jQuery( document ).trigger( "ready" ).unbind( "ready" );
+                               }
+                       }
+               }
+       },
+       
+       bindReady: function() {
+               if ( readyBound ) {
+                       return;
+               }
+
+               readyBound = true;
+
+               // Catch cases where $(document).ready() is called after the
+               // browser event has already occurred.
+               if ( document.readyState === "complete" ) {
+                       // Handle it asynchronously to allow scripts the opportunity to delay ready
+                       return setTimeout( jQuery.ready, 1 );
+               }
+
+               // Mozilla, Opera and webkit nightlies currently support this event
+               if ( document.addEventListener ) {
+                       // Use the handy event callback
+                       document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+                       
+                       // A fallback to window.onload, that will always work
+                       window.addEventListener( "load", jQuery.ready, false );
+
+               // If IE event model is used
+               } else if ( document.attachEvent ) {
+                       // ensure firing before onload,
+                       // maybe late but safe also for iframes
+                       document.attachEvent("onreadystatechange", DOMContentLoaded);
+                       
+                       // A fallback to window.onload, that will always work
+                       window.attachEvent( "onload", jQuery.ready );
+
+                       // If IE and not a frame
+                       // continually check to see if the document is ready
+                       var toplevel = false;
+
+                       try {
+                               toplevel = window.frameElement == null;
+                       } catch(e) {}
+
+                       if ( document.documentElement.doScroll && toplevel ) {
+                               doScrollCheck();
+                       }
+               }
+       },
+
+       // See test/unit/core.js for details concerning isFunction.
+       // Since version 1.3, DOM methods and functions like alert
+       // aren't supported. They return false on IE (#2968).
+       isFunction: function( obj ) {
+               return jQuery.type(obj) === "function";
+       },
+
+       isArray: Array.isArray || function( obj ) {
+               return jQuery.type(obj) === "array";
+       },
+
+       // A crude way of determining if an object is a window
+       isWindow: function( obj ) {
+               return obj && typeof obj === "object" && "setInterval" in obj;
+       },
+
+       isNaN: function( obj ) {
+               return obj == null || !rdigit.test( obj ) || isNaN( obj );
+       },
+
+       type: function( obj ) {
+               return obj == null ?
+                       String( obj ) :
+                       class2type[ toString.call(obj) ] || "object";
+       },
+
+       isPlainObject: function( obj ) {
+               // Must be an Object.
+               // Because of IE, we also have to check the presence of the constructor property.
+               // Make sure that DOM nodes and window objects don't pass through, as well
+               if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+                       return false;
+               }
+               
+               // Not own constructor property must be Object
+               if ( obj.constructor &&
+                       !hasOwn.call(obj, "constructor") &&
+                       !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+                       return false;
+               }
+               
+               // Own properties are enumerated firstly, so to speed up,
+               // if last one is own, then all properties are own.
+       
+               var key;
+               for ( key in obj ) {}
+               
+               return key === undefined || hasOwn.call( obj, key );
+       },
+
+       isEmptyObject: function( obj ) {
+               for ( var name in obj ) {
+                       return false;
+               }
+               return true;
+       },
+       
+       error: function( msg ) {
+               throw msg;
+       },
+       
+       parseJSON: function( data ) {
+               if ( typeof data !== "string" || !data ) {
+                       return null;
+               }
+
+               // Make sure leading/trailing whitespace is removed (IE can't handle it)
+               data = jQuery.trim( data );
+               
+               // Make sure the incoming data is actual JSON
+               // Logic borrowed from http://json.org/json2.js
+               if ( rvalidchars.test(data.replace(rvalidescape, "@")
+                       .replace(rvalidtokens, "]")
+                       .replace(rvalidbraces, "")) ) {
+
+                       // Try to use the native JSON parser first
+                       return window.JSON && window.JSON.parse ?
+                               window.JSON.parse( data ) :
+                               (new Function("return " + data))();
+
+               } else {
+                       jQuery.error( "Invalid JSON: " + data );
+               }
+       },
+
+       noop: function() {},
+
+       // Evalulates a script in a global context
+       globalEval: function( data ) {
+               if ( data && rnotwhite.test(data) ) {
+                       // Inspired by code by Andrea Giammarchi
+                       // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+                       var head = document.getElementsByTagName("head")[0] || document.documentElement,
+                               script = document.createElement("script");
+
+                       script.type = "text/javascript";
+
+                       if ( jQuery.support.scriptEval ) {
+                               script.appendChild( document.createTextNode( data ) );
+                       } else {
+                               script.text = data;
+                       }
+
+                       // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+                       // This arises when a base node is used (#2709).
+                       head.insertBefore( script, head.firstChild );
+                       head.removeChild( script );
+               }
+       },
+
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+       },
+
+       // args is for internal usage only
+       each: function( object, callback, args ) {
+               var name, i = 0,
+                       length = object.length,
+                       isObj = length === undefined || jQuery.isFunction(object);
+
+               if ( args ) {
+                       if ( isObj ) {
+                               for ( name in object ) {
+                                       if ( callback.apply( object[ name ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( ; i < length; ) {
+                                       if ( callback.apply( object[ i++ ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       }
+
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( isObj ) {
+                               for ( name in object ) {
+                                       if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( var value = object[0];
+                                       i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
+                       }
+               }
+
+               return object;
+       },
+
+       // Use native String.trim function wherever possible
+       trim: trim ?
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               trim.call( text );
+               } :
+
+               // Otherwise use our own trimming functionality
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+               },
+
+       // results is for internal usage only
+       makeArray: function( array, results ) {
+               var ret = results || [];
+
+               if ( array != null ) {
+                       // The window, strings (and functions) also have 'length'
+                       // The extra typeof function check is to prevent crashes
+                       // in Safari 2 (See: #3039)
+                       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+                       var type = jQuery.type(array);
+
+                       if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+                               push.call( ret, array );
+                       } else {
+                               jQuery.merge( ret, array );
+                       }
+               }
+
+               return ret;
+       },
+
+       inArray: function( elem, array ) {
+               if ( array.indexOf ) {
+                       return array.indexOf( elem );
+               }
+
+               for ( var i = 0, length = array.length; i < length; i++ ) {
+                       if ( array[ i ] === elem ) {
+                               return i;
+                       }
+               }
+
+               return -1;
+       },
+
+       merge: function( first, second ) {
+               var i = first.length,
+                       j = 0;
+
+               if ( typeof second.length === "number" ) {
+                       for ( var l = second.length; j < l; j++ ) {
+                               first[ i++ ] = second[ j ];
+                       }
+               
+               } else {
+                       while ( second[j] !== undefined ) {
+                               first[ i++ ] = second[ j++ ];
+                       }
+               }
+
+               first.length = i;
+
+               return first;
+       },
+
+       grep: function( elems, callback, inv ) {
+               var ret = [], retVal;
+               inv = !!inv;
+
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       retVal = !!callback( elems[ i ], i );
+                       if ( inv !== retVal ) {
+                               ret.push( elems[ i ] );
+                       }
+               }
+
+               return ret;
+       },
+
+       // arg is for internal usage only
+       map: function( elems, callback, arg ) {
+               var ret = [], value;
+
+               // Go through the array, translating each of the items to their
+               // new value (or values).
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       value = callback( elems[ i ], i, arg );
+
+                       if ( value != null ) {
+                               ret[ ret.length ] = value;
+                       }
+               }
+
+               return ret.concat.apply( [], ret );
+       },
+
+       // A global GUID counter for objects
+       guid: 1,
+
+       proxy: function( fn, proxy, thisObject ) {
+               if ( arguments.length === 2 ) {
+                       if ( typeof proxy === "string" ) {
+                               thisObject = fn;
+                               fn = thisObject[ proxy ];
+                               proxy = undefined;
+
+                       } else if ( proxy && !jQuery.isFunction( proxy ) ) {
+                               thisObject = proxy;
+                               proxy = undefined;
+                       }
+               }
+
+               if ( !proxy && fn ) {
+                       proxy = function() {
+                               return fn.apply( thisObject || this, arguments );
+                       };
+               }
+
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               if ( fn ) {
+                       proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+               }
+
+               // So proxy can be declared as an argument
+               return proxy;
+       },
+
+       // Mutifunctional method to get and set values to a collection
+       // The value/s can be optionally by executed if its a function
+       access: function( elems, key, value, exec, fn, pass ) {
+               var length = elems.length;
+       
+               // Setting many attributes
+               if ( typeof key === "object" ) {
+                       for ( var k in key ) {
+                               jQuery.access( elems, k, key[k], exec, fn, value );
+                       }
+                       return elems;
+               }
+       
+               // Setting one attribute
+               if ( value !== undefined ) {
+                       // Optionally, function values get executed if exec is true
+                       exec = !pass && exec && jQuery.isFunction(value);
+               
+                       for ( var i = 0; i < length; i++ ) {
+                               fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+                       }
+               
+                       return elems;
+               }
+       
+               // Getting an attribute
+               return length ? fn( elems[0], key ) : undefined;
+       },
+
+       now: function() {
+               return (new Date()).getTime();
+       },
+
+       // Use of jQuery.browser is frowned upon.
+       // More details: http://docs.jquery.com/Utilities/jQuery.browser
+       uaMatch: function( ua ) {
+               ua = ua.toLowerCase();
+
+               var match = rwebkit.exec( ua ) ||
+                       ropera.exec( ua ) ||
+                       rmsie.exec( ua ) ||
+                       ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+                       [];
+
+               return { browser: match[1] || "", version: match[2] || "0" };
+       },
+
+       browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+       class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+       jQuery.browser[ browserMatch.browser ] = true;
+       jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+       jQuery.browser.safari = true;
+}
+
+if ( indexOf ) {
+       jQuery.inArray = function( elem, array ) {
+               return indexOf.call( array, elem );
+       };
+}
+
+// Verify that \s matches non-breaking spaces
+// (IE fails on this test)
+if ( !rwhite.test( "\xA0" ) ) {
+       trimLeft = /^[\s\xA0]+/;
+       trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+       DOMContentLoaded = function() {
+               document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+               jQuery.ready();
+       };
+
+} else if ( document.attachEvent ) {
+       DOMContentLoaded = function() {
+               // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+               if ( document.readyState === "complete" ) {
+                       document.detachEvent( "onreadystatechange", DOMContentLoaded );
+                       jQuery.ready();
+               }
+       };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+       if ( jQuery.isReady ) {
+               return;
+       }
+
+       try {
+               // If IE is used, use the trick by Diego Perini
+               // http://javascript.nwbox.com/IEContentLoaded/
+               document.documentElement.doScroll("left");
+       } catch(e) {
+               setTimeout( doScrollCheck, 1 );
+               return;
+       }
+
+       // and execute any waiting functions
+       jQuery.ready();
+}
+
+// Expose jQuery to the global object
+return (window.jQuery = window.$ = jQuery);
+
+})();
+
+
+(function() {
+
+       jQuery.support = {};
+
+       var root = document.documentElement,
+               script = document.createElement("script"),
+               div = document.createElement("div"),
+               id = "script" + jQuery.now();
+
+       div.style.display = "none";
+       div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+       var all = div.getElementsByTagName("*"),
+               a = div.getElementsByTagName("a")[0],
+               select = document.createElement("select"),
+               opt = select.appendChild( document.createElement("option") );
+
+       // Can't get basic test support
+       if ( !all || !all.length || !a ) {
+               return;
+       }
+
+       jQuery.support = {
+               // IE strips leading whitespace when .innerHTML is used
+               leadingWhitespace: div.firstChild.nodeType === 3,
+
+               // Make sure that tbody elements aren't automatically inserted
+               // IE will insert them into empty tables
+               tbody: !div.getElementsByTagName("tbody").length,
+
+               // Make sure that link elements get serialized correctly by innerHTML
+               // This requires a wrapper element in IE
+               htmlSerialize: !!div.getElementsByTagName("link").length,
+
+               // Get the style information from getAttribute
+               // (IE uses .cssText insted)
+               style: /red/.test( a.getAttribute("style") ),
+
+               // Make sure that URLs aren't manipulated
+               // (IE normalizes it by default)
+               hrefNormalized: a.getAttribute("href") === "/a",
+
+               // Make sure that element opacity exists
+               // (IE uses filter instead)
+               // Use a regex to work around a WebKit issue. See #5145
+               opacity: /^0.55$/.test( a.style.opacity ),
+
+               // Verify style float existence
+               // (IE uses styleFloat instead of cssFloat)
+               cssFloat: !!a.style.cssFloat,
+
+               // Make sure that if no value is specified for a checkbox
+               // that it defaults to "on".
+               // (WebKit defaults to "" instead)
+               checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+               // Make sure that a selected-by-default option has a working selected property.
+               // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+               optSelected: opt.selected,
+
+               // Will be defined later
+               deleteExpando: true,
+               optDisabled: false,
+               checkClone: false,
+               scriptEval: false,
+               noCloneEvent: true,
+               boxModel: null,
+               inlineBlockNeedsLayout: false,
+               shrinkWrapBlocks: false,
+               reliableHiddenOffsets: true
+       };
+
+       // Make sure that the options inside disabled selects aren't marked as disabled
+       // (WebKit marks them as diabled)
+       select.disabled = true;
+       jQuery.support.optDisabled = !opt.disabled;
+
+       script.type = "text/javascript";
+       try {
+               script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+       } catch(e) {}
+
+       root.insertBefore( script, root.firstChild );
+
+       // Make sure that the execution of code works by injecting a script
+       // tag with appendChild/createTextNode
+       // (IE doesn't support this, fails, and uses .text instead)
+       if ( window[ id ] ) {
+               jQuery.support.scriptEval = true;
+               delete window[ id ];
+       }
+
+       // Test to see if it's possible to delete an expando from an element
+       // Fails in Internet Explorer
+       try {
+               delete script.test;
+
+       } catch(e) {
+               jQuery.support.deleteExpando = false;
+       }
+
+       root.removeChild( script );
+
+       if ( div.attachEvent && div.fireEvent ) {
+               div.attachEvent("onclick", function click() {
+                       // Cloning a node shouldn't copy over any
+                       // bound event handlers (IE does this)
+                       jQuery.support.noCloneEvent = false;
+                       div.detachEvent("onclick", click);
+               });
+               div.cloneNode(true).fireEvent("onclick");
+       }
+
+       div = document.createElement("div");
+       div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
+
+       var fragment = document.createDocumentFragment();
+       fragment.appendChild( div.firstChild );
+
+       // WebKit doesn't clone checked state correctly in fragments
+       jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
+
+       // Figure out if the W3C box model works as expected
+       // document.body must exist before we can do this
+       jQuery(function() {
+               var div = document.createElement("div");
+               div.style.width = div.style.paddingLeft = "1px";
+
+               document.body.appendChild( div );
+               jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+
+               if ( "zoom" in div.style ) {
+                       // Check if natively block-level elements act like inline-block
+                       // elements when setting their display to 'inline' and giving
+                       // them layout
+                       // (IE < 8 does this)
+                       div.style.display = "inline";
+                       div.style.zoom = 1;
+                       jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
+
+                       // Check if elements with layout shrink-wrap their children
+                       // (IE 6 does this)
+                       div.style.display = "";
+                       div.innerHTML = "<div style='width:4px;'></div>";
+                       jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
+               }
+
+               div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
+               var tds = div.getElementsByTagName("td");
+
+               // Check if table cells still have offsetWidth/Height when they are set
+               // to display:none and there are still other visible table cells in a
+               // table row; if so, offsetWidth/Height are not reliable for use when
+               // determining if an element has been hidden directly using
+               // display:none (it is still safe to use offsets if a parent element is
+               // hidden; don safety goggles and see bug #4512 for more information).
+               // (only IE 8 fails this test)
+               jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
+
+               tds[0].style.display = "";
+               tds[1].style.display = "none";
+
+               // Check if empty table cells still have offsetWidth/Height
+               // (IE < 8 fail this test)
+               jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
+               div.innerHTML = "";
+
+               document.body.removeChild( div ).style.display = "none";
+               div = tds = null;
+       });
+
+       // Technique from Juriy Zaytsev
+       // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+       var eventSupported = function( eventName ) {
+               var el = document.createElement("div");
+               eventName = "on" + eventName;
+
+               var isSupported = (eventName in el);
+               if ( !isSupported ) {
+                       el.setAttribute(eventName, "return;");
+                       isSupported = typeof el[eventName] === "function";
+               }
+               el = null;
+
+               return isSupported;
+       };
+
+       jQuery.support.submitBubbles = eventSupported("submit");
+       jQuery.support.changeBubbles = eventSupported("change");
+
+       // release memory in IE
+       root = script = div = all = a = null;
+})();
+
+
+
+var windowData = {},
+       rbrace = /^(?:\{.*\}|\[.*\])$/;
+
+jQuery.extend({
+       cache: {},
+
+       // Please use with caution
+       uuid: 0,
+
+       // Unique for each copy of jQuery on the page   
+       expando: "jQuery" + jQuery.now(),
+
+       // The following elements throw uncatchable exceptions if you
+       // attempt to add expando properties to them.
+       noData: {
+               "embed": true,
+               // Ban all objects except for Flash (which handle expandos)
+               "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+               "applet": true
+       },
+
+       data: function( elem, name, data ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var isNode = elem.nodeType,
+                       id = isNode ? elem[ jQuery.expando ] : null,
+                       cache = jQuery.cache, thisCache;
+
+               if ( isNode && !id && typeof name === "string" && data === undefined ) {
+                       return;
+               }
+
+               // Get the data from the object directly
+               if ( !isNode ) {
+                       cache = elem;
+
+               // Compute a unique ID for the element
+               } else if ( !id ) {
+                       elem[ jQuery.expando ] = id = ++jQuery.uuid;
+               }
+
+               // Avoid generating a new cache unless none exists and we
+               // want to manipulate it.
+               if ( typeof name === "object" ) {
+                       if ( isNode ) {
+                               cache[ id ] = jQuery.extend(cache[ id ], name);
+
+                       } else {
+                               jQuery.extend( cache, name );
+                       }
+
+               } else if ( isNode && !cache[ id ] ) {
+                       cache[ id ] = {};
+               }
+
+               thisCache = isNode ? cache[ id ] : cache;
+
+               // Prevent overriding the named cache with undefined values
+               if ( data !== undefined ) {
+                       thisCache[ name ] = data;
+               }
+
+               return typeof name === "string" ? thisCache[ name ] : thisCache;
+       },
+
+       removeData: function( elem, name ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               elem = elem == window ?
+                       windowData :
+                       elem;
+
+               var isNode = elem.nodeType,
+                       id = isNode ? elem[ jQuery.expando ] : elem,
+                       cache = jQuery.cache,
+                       thisCache = isNode ? cache[ id ] : id;
+
+               // If we want to remove a specific section of the element's data
+               if ( name ) {
+                       if ( thisCache ) {
+                               // Remove the section of cache data
+                               delete thisCache[ name ];
+
+                               // If we've removed all the data, remove the element's cache
+                               if ( isNode && jQuery.isEmptyObject(thisCache) ) {
+                                       jQuery.removeData( elem );
+                               }
+                       }
+
+               // Otherwise, we want to remove all of the element's data
+               } else {
+                       if ( isNode && jQuery.support.deleteExpando ) {
+                               delete elem[ jQuery.expando ];
+
+                       } else if ( elem.removeAttribute ) {
+                               elem.removeAttribute( jQuery.expando );
+
+                       // Completely remove the data cache
+                       } else if ( isNode ) {
+                               delete cache[ id ];
+
+                       // Remove all fields from the object
+                       } else {
+                               for ( var n in elem ) {
+                                       delete elem[ n ];
+                               }
+                       }
+               }
+       },
+
+       // A method for determining if a DOM node can handle the data expando
+       acceptData: function( elem ) {
+               if ( elem.nodeName ) {
+                       var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+                       if ( match ) {
+                               return !(match === true || elem.getAttribute("classid") !== match);
+                       }
+               }
+
+               return true;
+       }
+});
+
+jQuery.fn.extend({
+       data: function( key, value ) {
+               var data = null;
+
+               if ( typeof key === "undefined" ) {
+                       if ( this.length ) {
+                               var attr = this[0].attributes, name;
+                               data = jQuery.data( this[0] );
+
+                               for ( var i = 0, l = attr.length; i < l; i++ ) {
+                                       name = attr[i].name;
+
+                                       if ( name.indexOf( "data-" ) === 0 ) {
+                                               name = name.substr( 5 );
+                                               dataAttr( this[0], name, data[ name ] );
+                                       }
+                               }
+                       }
+
+                       return data;
+
+               } else if ( typeof key === "object" ) {
+                       return this.each(function() {
+                               jQuery.data( this, key );
+                       });
+               }
+
+               var parts = key.split(".");
+               parts[1] = parts[1] ? "." + parts[1] : "";
+
+               if ( value === undefined ) {
+                       data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+                       // Try to fetch any internally stored data first
+                       if ( data === undefined && this.length ) {
+                               data = jQuery.data( this[0], key );
+                               data = dataAttr( this[0], key, data );
+                       }
+
+                       return data === undefined && parts[1] ?
+                               this.data( parts[0] ) :
+                               data;
+
+               } else {
+                       return this.each(function() {
+                               var $this = jQuery( this ),
+                                       args = [ parts[0], value ];
+
+                               $this.triggerHandler( "setData" + parts[1] + "!", args );
+                               jQuery.data( this, key, value );
+                               $this.triggerHandler( "changeData" + parts[1] + "!", args );
+                       });
+               }
+       },
+
+       removeData: function( key ) {
+               return this.each(function() {
+                       jQuery.removeData( this, key );
+               });
+       }
+});
+
+function dataAttr( elem, key, data ) {
+       // If nothing was found internally, try to fetch any
+       // data from the HTML5 data-* attribute
+       if ( data === undefined && elem.nodeType === 1 ) {
+               data = elem.getAttribute( "data-" + key );
+
+               if ( typeof data === "string" ) {
+                       try {
+                               data = data === "true" ? true :
+                               data === "false" ? false :
+                               data === "null" ? null :
+                               !jQuery.isNaN( data ) ? parseFloat( data ) :
+                                       rbrace.test( data ) ? jQuery.parseJSON( data ) :
+                                       data;
+                       } catch( e ) {}
+
+                       // Make sure we set the data so it isn't changed later
+                       jQuery.data( elem, key, data );
+
+               } else {
+                       data = undefined;
+               }
+       }
+
+       return data;
+}
+
+
+
+
+jQuery.extend({
+       queue: function( elem, type, data ) {
+               if ( !elem ) {
+                       return;
+               }
+
+               type = (type || "fx") + "queue";
+               var q = jQuery.data( elem, type );
+
+               // Speed up dequeue by getting out quickly if this is just a lookup
+               if ( !data ) {
+                       return q || [];
+               }
+
+               if ( !q || jQuery.isArray(data) ) {
+                       q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+               } else {
+                       q.push( data );
+               }
+
+               return q;
+       },
+
+       dequeue: function( elem, type ) {
+               type = type || "fx";
+
+               var queue = jQuery.queue( elem, type ),
+                       fn = queue.shift();
+
+               // If the fx queue is dequeued, always remove the progress sentinel
+               if ( fn === "inprogress" ) {
+                       fn = queue.shift();
+               }
+
+               if ( fn ) {
+                       // Add a progress sentinel to prevent the fx queue from being
+                       // automatically dequeued
+                       if ( type === "fx" ) {
+                               queue.unshift("inprogress");
+                       }
+
+                       fn.call(elem, function() {
+                               jQuery.dequeue(elem, type);
+                       });
+               }
+       }
+});
+
+jQuery.fn.extend({
+       queue: function( type, data ) {
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+               }
+
+               if ( data === undefined ) {
+                       return jQuery.queue( this[0], type );
+               }
+               return this.each(function( i ) {
+                       var queue = jQuery.queue( this, type, data );
+
+                       if ( type === "fx" && queue[0] !== "inprogress" ) {
+                               jQuery.dequeue( this, type );
+                       }
+               });
+       },
+       dequeue: function( type ) {
+               return this.each(function() {
+                       jQuery.dequeue( this, type );
+               });
+       },
+
+       // Based off of the plugin by Clint Helfers, with permission.
+       // http://blindsignals.com/index.php/2009/07/jquery-delay/
+       delay: function( time, type ) {
+               time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+               type = type || "fx";
+
+               return this.queue( type, function() {
+                       var elem = this;
+                       setTimeout(function() {
+                               jQuery.dequeue( elem, type );
+                       }, time );
+               });
+       },
+
+       clearQueue: function( type ) {
+               return this.queue( type || "fx", [] );
+       }
+});
+
+
+
+
+var rclass = /[\n\t]/g,
+       rspaces = /\s+/,
+       rreturn = /\r/g,
+       rspecialurl = /^(?:href|src|style)$/,
+       rtype = /^(?:button|input)$/i,
+       rfocusable = /^(?:button|input|object|select|textarea)$/i,
+       rclickable = /^a(?:rea)?$/i,
+       rradiocheck = /^(?:radio|checkbox)$/i;
+
+jQuery.props = {
+       "for": "htmlFor",
+       "class": "className",
+       readonly: "readOnly",
+       maxlength: "maxLength",
+       cellspacing: "cellSpacing",
+       rowspan: "rowSpan",
+       colspan: "colSpan",
+       tabindex: "tabIndex",
+       usemap: "useMap",
+       frameborder: "frameBorder"
+};
+
+jQuery.fn.extend({
+       attr: function( name, value ) {
+               return jQuery.access( this, name, value, true, jQuery.attr );
+       },
+
+       removeAttr: function( name, fn ) {
+               return this.each(function(){
+                       jQuery.attr( this, name, "" );
+                       if ( this.nodeType === 1 ) {
+                               this.removeAttribute( name );
+                       }
+               });
+       },
+
+       addClass: function( value ) {
+               if ( jQuery.isFunction(value) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               self.addClass( value.call(this, i, self.attr("class")) );
+                       });
+               }
+
+               if ( value && typeof value === "string" ) {
+                       var classNames = (value || "").split( rspaces );
+
+                       for ( var i = 0, l = this.length; i < l; i++ ) {
+                               var elem = this[i];
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !elem.className ) {
+                                               elem.className = value;
+
+                                       } else {
+                                               var className = " " + elem.className + " ",
+                                                       setClass = elem.className;
+
+                                               for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+                                                       if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
+                                                               setClass += " " + classNames[c];
+                                                       }
+                                               }
+                                               elem.className = jQuery.trim( setClass );
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       removeClass: function( value ) {
+               if ( jQuery.isFunction(value) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               self.removeClass( value.call(this, i, self.attr("class")) );
+                       });
+               }
+
+               if ( (value && typeof value === "string") || value === undefined ) {
+                       var classNames = (value || "").split( rspaces );
+
+                       for ( var i = 0, l = this.length; i < l; i++ ) {
+                               var elem = this[i];
+
+                               if ( elem.nodeType === 1 && elem.className ) {
+                                       if ( value ) {
+                                               var className = (" " + elem.className + " ").replace(rclass, " ");
+                                               for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+                                                       className = className.replace(" " + classNames[c] + " ", " ");
+                                               }
+                                               elem.className = jQuery.trim( className );
+
+                                       } else {
+                                               elem.className = "";
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       toggleClass: function( value, stateVal ) {
+               var type = typeof value,
+                       isBool = typeof stateVal === "boolean";
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
+                       });
+               }
+
+               return this.each(function() {
+                       if ( type === "string" ) {
+                               // toggle individual class names
+                               var className,
+                                       i = 0,
+                                       self = jQuery( this ),
+                                       state = stateVal,
+                                       classNames = value.split( rspaces );
+
+                               while ( (className = classNames[ i++ ]) ) {
+                                       // check each className given, space seperated list
+                                       state = isBool ? state : !self.hasClass( className );
+                                       self[ state ? "addClass" : "removeClass" ]( className );
+                               }
+
+                       } else if ( type === "undefined" || type === "boolean" ) {
+                               if ( this.className ) {
+                                       // store className if set
+                                       jQuery.data( this, "__className__", this.className );
+                               }
+
+                               // toggle whole className
+                               this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
+                       }
+               });
+       },
+
+       hasClass: function( selector ) {
+               var className = " " + selector + " ";
+               for ( var i = 0, l = this.length; i < l; i++ ) {
+                       if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       },
+
+       val: function( value ) {
+               if ( !arguments.length ) {
+                       var elem = this[0];
+
+                       if ( elem ) {
+                               if ( jQuery.nodeName( elem, "option" ) ) {
+                                       // attributes.value is undefined in Blackberry 4.7 but
+                                       // uses .value. See #6932
+                                       var val = elem.attributes.value;
+                                       return !val || val.specified ? elem.value : elem.text;
+                               }
+
+                               // We need to handle select boxes special
+                               if ( jQuery.nodeName( elem, "select" ) ) {
+                                       var index = elem.selectedIndex,
+                                               values = [],
+                                               options = elem.options,
+                                               one = elem.type === "select-one";
+
+                                       // Nothing was selected
+                                       if ( index < 0 ) {
+                                               return null;
+                                       }
+
+                                       // Loop through all the selected options
+                                       for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+                                               var option = options[ i ];
+
+                                               // Don't return options that are disabled or in a disabled optgroup
+                                               if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && 
+                                                               (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+                                                       // Get the specific value for the option
+                                                       value = jQuery(option).val();
+
+                                                       // We don't need an array for one selects
+                                                       if ( one ) {
+                                                               return value;
+                                                       }
+
+                                                       // Multi-Selects return an array
+                                                       values.push( value );
+                                               }
+                                       }
+
+                                       return values;
+                               }
+
+                               // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+                               if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+                                       return elem.getAttribute("value") === null ? "on" : elem.value;
+                               }
+                               
+
+                               // Everything else, we just grab the value
+                               return (elem.value || "").replace(rreturn, "");
+
+                       }
+
+                       return undefined;
+               }
+
+               var isFunction = jQuery.isFunction(value);
+
+               return this.each(function(i) {
+                       var self = jQuery(this), val = value;
+
+                       if ( this.nodeType !== 1 ) {
+                               return;
+                       }
+
+                       if ( isFunction ) {
+                               val = value.call(this, i, self.val());
+                       }
+
+                       // Treat null/undefined as ""; convert numbers to string
+                       if ( val == null ) {
+                               val = "";
+                       } else if ( typeof val === "number" ) {
+                               val += "";
+                       } else if ( jQuery.isArray(val) ) {
+                               val = jQuery.map(val, function (value) {
+                                       return value == null ? "" : value + "";
+                               });
+                       }
+
+                       if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+                               this.checked = jQuery.inArray( self.val(), val ) >= 0;
+
+                       } else if ( jQuery.nodeName( this, "select" ) ) {
+                               var values = jQuery.makeArray(val);
+
+                               jQuery( "option", this ).each(function() {
+                                       this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+                               });
+
+                               if ( !values.length ) {
+                                       this.selectedIndex = -1;
+                               }
+
+                       } else {
+                               this.value = val;
+                       }
+               });
+       }
+});
+
+jQuery.extend({
+       attrFn: {
+               val: true,
+               css: true,
+               html: true,
+               text: true,
+               data: true,
+               width: true,
+               height: true,
+               offset: true
+       },
+               
+       attr: function( elem, name, value, pass ) {
+               // don't set attributes on text and comment nodes
+               if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+                       return undefined;
+               }
+
+               if ( pass && name in jQuery.attrFn ) {
+                       return jQuery(elem)[name](value);
+               }
+
+               var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
+                       // Whether we are setting (or getting)
+                       set = value !== undefined;
+
+               // Try to normalize/fix the name
+               name = notxml && jQuery.props[ name ] || name;
+
+               // These attributes require special treatment
+               var special = rspecialurl.test( name );
+
+               // Safari mis-reports the default selected property of an option
+               // Accessing the parent's selectedIndex property fixes it
+               if ( name === "selected" && !jQuery.support.optSelected ) {
+                       var parent = elem.parentNode;
+                       if ( parent ) {
+                               parent.selectedIndex;
+
+                               // Make sure that it also works with optgroups, see #5701
+                               if ( parent.parentNode ) {
+                                       parent.parentNode.selectedIndex;
+                               }
+                       }
+               }
+
+               // If applicable, access the attribute via the DOM 0 way
+               // 'in' checks fail in Blackberry 4.7 #6931
+               if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
+                       if ( set ) {
+                               // We can't allow the type property to be changed (since it causes problems in IE)
+                               if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
+                                       jQuery.error( "type property can't be changed" );
+                               }
+
+                               if ( value === null ) {
+                                       if ( elem.nodeType === 1 ) {
+                                               elem.removeAttribute( name );
+                                       }
+
+                               } else {
+                                       elem[ name ] = value;
+                               }
+                       }
+
+                       // browsers index elements by id/name on forms, give priority to attributes.
+                       if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
+                               return elem.getAttributeNode( name ).nodeValue;
+                       }
+
+                       // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+                       // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+                       if ( name === "tabIndex" ) {
+                               var attributeNode = elem.getAttributeNode( "tabIndex" );
+
+                               return attributeNode && attributeNode.specified ?
+                                       attributeNode.value :
+                                       rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+                                               0 :
+                                               undefined;
+                       }
+
+                       return elem[ name ];
+               }
+
+               if ( !jQuery.support.style && notxml && name === "style" ) {
+                       if ( set ) {
+                               elem.style.cssText = "" + value;
+                       }
+
+                       return elem.style.cssText;
+               }
+
+               if ( set ) {
+                       // convert the value to a string (all browsers do this but IE) see #1070
+                       elem.setAttribute( name, "" + value );
+               }
+
+               // Ensure that missing attributes return undefined
+               // Blackberry 4.7 returns "" from getAttribute #6938
+               if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
+                       return undefined;
+               }
+
+               var attr = !jQuery.support.hrefNormalized && notxml && special ?
+                               // Some attributes require a special call on IE
+                               elem.getAttribute( name, 2 ) :
+                               elem.getAttribute( name );
+
+               // Non-existent attributes return null, we normalize to undefined
+               return attr === null ? undefined : attr;
+       }
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+       rformElems = /^(?:textarea|input|select)$/i,
+       rperiod = /\./g,
+       rspace = / /g,
+       rescape = /[^\w\s.|`]/g,
+       fcleanup = function( nm ) {
+               return nm.replace(rescape, "\\$&");
+       },
+       focusCounts = { focusin: 0, focusout: 0 };
+
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
+
+       // Bind an event to an element
+       // Original by Dean Edwards
+       add: function( elem, types, handler, data ) {
+               if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+                       return;
+               }
+
+               // For whatever reason, IE has trouble passing the window object
+               // around, causing it to be cloned in the process
+               if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
+                       elem = window;
+               }
+
+               if ( handler === false ) {
+                       handler = returnFalse;
+               } else if ( !handler ) {
+                       // Fixes bug #7229. Fix recommended by jdalton
+                 return;
+               }
+
+               var handleObjIn, handleObj;
+
+               if ( handler.handler ) {
+                       handleObjIn = handler;
+                       handler = handleObjIn.handler;
+               }
+
+               // Make sure that the function being executed has a unique ID
+               if ( !handler.guid ) {
+                       handler.guid = jQuery.guid++;
+               }
+
+               // Init the element's event structure
+               var elemData = jQuery.data( elem );
+
+               // If no elemData is found then we must be trying to bind to one of the
+               // banned noData elements
+               if ( !elemData ) {
+                       return;
+               }
+
+               // Use a key less likely to result in collisions for plain JS objects.
+               // Fixes bug #7150.
+               var eventKey = elem.nodeType ? "events" : "__events__",
+                       events = elemData[ eventKey ],
+                       eventHandle = elemData.handle;
+                       
+               if ( typeof events === "function" ) {
+                       // On plain objects events is a fn that holds the the data
+                       // which prevents this data from being JSON serialized
+                       // the function does not need to be called, it just contains the data
+                       eventHandle = events.handle;
+                       events = events.events;
+
+               } else if ( !events ) {
+                       if ( !elem.nodeType ) {
+                               // On plain objects, create a fn that acts as the holder
+                               // of the values to avoid JSON serialization of event data
+                               elemData[ eventKey ] = elemData = function(){};
+                       }
+
+                       elemData.events = events = {};
+               }
+
+               if ( !eventHandle ) {
+                       elemData.handle = eventHandle = function() {
+                               // Handle the second event of a trigger and when
+                               // an event is called after a page has unloaded
+                               return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+                                       jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+                                       undefined;
+                       };
+               }
+
+               // Add elem as a property of the handle function
+               // This is to prevent a memory leak with non-native events in IE.
+               eventHandle.elem = elem;
+
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               types = types.split(" ");
+
+               var type, i = 0, namespaces;
+
+               while ( (type = types[ i++ ]) ) {
+                       handleObj = handleObjIn ?
+                               jQuery.extend({}, handleObjIn) :
+                               { handler: handler, data: data };
+
+                       // Namespaced event handlers
+                       if ( type.indexOf(".") > -1 ) {
+                               namespaces = type.split(".");
+                               type = namespaces.shift();
+                               handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+                       } else {
+                               namespaces = [];
+                               handleObj.namespace = "";
+                       }
+
+                       handleObj.type = type;
+                       if ( !handleObj.guid ) {
+                               handleObj.guid = handler.guid;
+                       }
+
+                       // Get the current list of functions bound to this event
+                       var handlers = events[ type ],
+                               special = jQuery.event.special[ type ] || {};
+
+                       // Init the event handler queue
+                       if ( !handlers ) {
+                               handlers = events[ type ] = [];
+
+                               // Check for a special event handler
+                               // Only use addEventListener/attachEvent if the special
+                               // events handler returns false
+                               if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+                                       // Bind the global event handler to the element
+                                       if ( elem.addEventListener ) {
+                                               elem.addEventListener( type, eventHandle, false );
+
+                                       } else if ( elem.attachEvent ) {
+                                               elem.attachEvent( "on" + type, eventHandle );
+                                       }
+                               }
+                       }
+                       
+                       if ( special.add ) { 
+                               special.add.call( elem, handleObj ); 
+
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
+                       }
+
+                       // Add the function to the element's handler list
+                       handlers.push( handleObj );
+
+                       // Keep track of which events have been used, for global triggering
+                       jQuery.event.global[ type ] = true;
+               }
+
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+
+       global: {},
+
+       // Detach an event or set of events from an element
+       remove: function( elem, types, handler, pos ) {
+               // don't do events on text and comment nodes
+               if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+                       return;
+               }
+
+               if ( handler === false ) {
+                       handler = returnFalse;
+               }
+
+               var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+                       eventKey = elem.nodeType ? "events" : "__events__",
+                       elemData = jQuery.data( elem ),
+                       events = elemData && elemData[ eventKey ];
+
+               if ( !elemData || !events ) {
+                       return;
+               }
+               
+               if ( typeof events === "function" ) {
+                       elemData = events;
+                       events = events.events;
+               }
+
+               // types is actually an event object here
+               if ( types && types.type ) {
+                       handler = types.handler;
+                       types = types.type;
+               }
+
+               // Unbind all events for the element
+               if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+                       types = types || "";
+
+                       for ( type in events ) {
+                               jQuery.event.remove( elem, type + types );
+                       }
+
+                       return;
+               }
+
+               // Handle multiple events separated by a space
+               // jQuery(...).unbind("mouseover mouseout", fn);
+               types = types.split(" ");
+
+               while ( (type = types[ i++ ]) ) {
+                       origType = type;
+                       handleObj = null;
+                       all = type.indexOf(".") < 0;
+                       namespaces = [];
+
+                       if ( !all ) {
+                               // Namespaced event handlers
+                               namespaces = type.split(".");
+                               type = namespaces.shift();
+
+                               namespace = new RegExp("(^|\\.)" + 
+                                       jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
+                       }
+
+                       eventType = events[ type ];
+
+                       if ( !eventType ) {
+                               continue;
+                       }
+
+                       if ( !handler ) {
+                               for ( j = 0; j < eventType.length; j++ ) {
+                                       handleObj = eventType[ j ];
+
+                                       if ( all || namespace.test( handleObj.namespace ) ) {
+                                               jQuery.event.remove( elem, origType, handleObj.handler, j );
+                                               eventType.splice( j--, 1 );
+                                       }
+                               }
+
+                               continue;
+                       }
+
+                       special = jQuery.event.special[ type ] || {};
+
+                       for ( j = pos || 0; j < eventType.length; j++ ) {
+                               handleObj = eventType[ j ];
+
+                               if ( handler.guid === handleObj.guid ) {
+                                       // remove the given handler for the given type
+                                       if ( all || namespace.test( handleObj.namespace ) ) {
+                                               if ( pos == null ) {
+                                                       eventType.splice( j--, 1 );
+                                               }
+
+                                               if ( special.remove ) {
+                                                       special.remove.call( elem, handleObj );
+                                               }
+                                       }
+
+                                       if ( pos != null ) {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       // remove generic event handler if no more handlers exist
+                       if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+                               if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+                                       jQuery.removeEvent( elem, type, elemData.handle );
+                               }
+
+                               ret = null;
+                               delete events[ type ];
+                       }
+               }
+
+               // Remove the expando if it's no longer used
+               if ( jQuery.isEmptyObject( events ) ) {
+                       var handle = elemData.handle;
+                       if ( handle ) {
+                               handle.elem = null;
+                       }
+
+                       delete elemData.events;
+                       delete elemData.handle;
+
+                       if ( typeof elemData === "function" ) {
+                               jQuery.removeData( elem, eventKey );
+
+                       } else if ( jQuery.isEmptyObject( elemData ) ) {
+                               jQuery.removeData( elem );
+                       }
+               }
+       },
+
+       // bubbling is internal
+       trigger: function( event, data, elem /*, bubbling */ ) {
+               // Event object or event type
+               var type = event.type || event,
+                       bubbling = arguments[3];
+
+               if ( !bubbling ) {
+                       event = typeof event === "object" ?
+                               // jQuery.Event object
+                               event[ jQuery.expando ] ? event :
+                               // Object literal
+                               jQuery.extend( jQuery.Event(type), event ) :
+                               // Just the event type (string)
+                               jQuery.Event(type);
+
+                       if ( type.indexOf("!") >= 0 ) {
+                               event.type = type = type.slice(0, -1);
+                               event.exclusive = true;
+                       }
+
+                       // Handle a global trigger
+                       if ( !elem ) {
+                               // Don't bubble custom events when global (to avoid too much overhead)
+                               event.stopPropagation();
+
+                               // Only trigger if we've ever bound an event for it
+                               if ( jQuery.event.global[ type ] ) {
+                                       jQuery.each( jQuery.cache, function() {
+                                               if ( this.events && this.events[type] ) {
+                                                       jQuery.event.trigger( event, data, this.handle.elem );
+                                               }
+                                       });
+                               }
+                       }
+
+                       // Handle triggering a single element
+
+                       // don't do events on text and comment nodes
+                       if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+                               return undefined;
+                       }
+
+                       // Clean up in case it is reused
+                       event.result = undefined;
+                       event.target = elem;
+
+                       // Clone the incoming data, if any
+                       data = jQuery.makeArray( data );
+                       data.unshift( event );
+               }
+
+               event.currentTarget = elem;
+
+               // Trigger the event, it is assumed that "handle" is a function
+               var handle = elem.nodeType ?
+                       jQuery.data( elem, "handle" ) :
+                       (jQuery.data( elem, "__events__" ) || {}).handle;
+
+               if ( handle ) {
+                       handle.apply( elem, data );
+               }
+
+               var parent = elem.parentNode || elem.ownerDocument;
+
+               // Trigger an inline bound script
+               try {
+                       if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+                               if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+                                       event.result = false;
+                                       event.preventDefault();
+                               }
+                       }
+
+               // prevent IE from throwing an error for some elements with some event types, see #3533
+               } catch (inlineError) {}
+
+               if ( !event.isPropagationStopped() && parent ) {
+                       jQuery.event.trigger( event, data, parent, true );
+
+               } else if ( !event.isDefaultPrevented() ) {
+                       var old,
+                               target = event.target,
+                               targetType = type.replace( rnamespaces, "" ),
+                               isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
+                               special = jQuery.event.special[ targetType ] || {};
+
+                       if ( (!special._default || special._default.call( elem, event ) === false) && 
+                               !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+                               try {
+                                       if ( target[ targetType ] ) {
+                                               // Make sure that we don't accidentally re-trigger the onFOO events
+                                               old = target[ "on" + targetType ];
+
+                                               if ( old ) {
+                                                       target[ "on" + targetType ] = null;
+                                               }
+
+                                               jQuery.event.triggered = true;
+                                               target[ targetType ]();
+                                       }
+
+                               // prevent IE from throwing an error for some elements with some event types, see #3533
+                               } catch (triggerError) {}
+
+                               if ( old ) {
+                                       target[ "on" + targetType ] = old;
+                               }
+
+                               jQuery.event.triggered = false;
+                       }
+               }
+       },
+
+       handle: function( event ) {
+               var all, handlers, namespaces, namespace_re, events,
+                       namespace_sort = [],
+                       args = jQuery.makeArray( arguments );
+
+               event = args[0] = jQuery.event.fix( event || window.event );
+               event.currentTarget = this;
+
+               // Namespaced event handlers
+               all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+               if ( !all ) {
+                       namespaces = event.type.split(".");
+                       event.type = namespaces.shift();
+                       namespace_sort = namespaces.slice(0).sort();
+                       namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
+               }
+
+               event.namespace = event.namespace || namespace_sort.join(".");
+
+               events = jQuery.data(this, this.nodeType ? "events" : "__events__");
+
+               if ( typeof events === "function" ) {
+                       events = events.events;
+               }
+
+               handlers = (events || {})[ event.type ];
+
+               if ( events && handlers ) {
+                       // Clone the handlers to prevent manipulation
+                       handlers = handlers.slice(0);
+
+                       for ( var j = 0, l = handlers.length; j < l; j++ ) {
+                               var handleObj = handlers[ j ];
+
+                               // Filter the functions by class
+                               if ( all || namespace_re.test( handleObj.namespace ) ) {
+                                       // Pass in a reference to the handler function itself
+                                       // So that we can later remove it
+                                       event.handler = handleObj.handler;
+                                       event.data = handleObj.data;
+                                       event.handleObj = handleObj;
+       
+                                       var ret = handleObj.handler.apply( this, args );
+
+                                       if ( ret !== undefined ) {
+                                               event.result = ret;
+                                               if ( ret === false ) {
+                                                       event.preventDefault();
+                                                       event.stopPropagation();
+                                               }
+                                       }
+
+                                       if ( event.isImmediatePropagationStopped() ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               return event.result;
+       },
+
+       props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+
+       fix: function( event ) {
+               if ( event[ jQuery.expando ] ) {
+                       return event;
+               }
+
+               // store a copy of the original event object
+               // and "clone" to set read-only properties
+               var originalEvent = event;
+               event = jQuery.Event( originalEvent );
+
+               for ( var i = this.props.length, prop; i; ) {
+                       prop = this.props[ --i ];
+                       event[ prop ] = originalEvent[ prop ];
+               }
+
+               // Fix target property, if necessary
+               if ( !event.target ) {
+                       // Fixes #1925 where srcElement might not be defined either
+                       event.target = event.srcElement || document;
+               }
+
+               // check if target is a textnode (safari)
+               if ( event.target.nodeType === 3 ) {
+                       event.target = event.target.parentNode;
+               }
+
+               // Add relatedTarget, if necessary
+               if ( !event.relatedTarget && event.fromElement ) {
+                       event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+               }
+
+               // Calculate pageX/Y if missing and clientX/Y available
+               if ( event.pageX == null && event.clientX != null ) {
+                       var doc = document.documentElement,
+                               body = document.body;
+
+                       event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+                       event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
+               }
+
+               // Add which for key events
+               if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
+                       event.which = event.charCode != null ? event.charCode : event.keyCode;
+               }
+
+               // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+               if ( !event.metaKey && event.ctrlKey ) {
+                       event.metaKey = event.ctrlKey;
+               }
+
+               // Add which for click: 1 === left; 2 === middle; 3 === right
+               // Note: button is not normalized, so don't use it
+               if ( !event.which && event.button !== undefined ) {
+                       event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+               }
+
+               return event;
+       },
+
+       // Deprecated, use jQuery.guid instead
+       guid: 1E8,
+
+       // Deprecated, use jQuery.proxy instead
+       proxy: jQuery.proxy,
+
+       special: {
+               ready: {
+                       // Make sure the ready event is setup
+                       setup: jQuery.bindReady,
+                       teardown: jQuery.noop
+               },
+
+               live: {
+                       add: function( handleObj ) {
+                               jQuery.event.add( this,
+                                       liveConvert( handleObj.origType, handleObj.selector ),
+                                       jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); 
+                       },
+
+                       remove: function( handleObj ) {
+                               jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
+                       }
+               },
+
+               beforeunload: {
+                       setup: function( data, namespaces, eventHandle ) {
+                               // We only want to do this special case on windows
+                               if ( jQuery.isWindow( this ) ) {
+                                       this.onbeforeunload = eventHandle;
+                               }
+                       },
+
+                       teardown: function( namespaces, eventHandle ) {
+                               if ( this.onbeforeunload === eventHandle ) {
+                                       this.onbeforeunload = null;
+                               }
+                       }
+               }
+       }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+       function( elem, type, handle ) {
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
+       } : 
+       function( elem, type, handle ) {
+               if ( elem.detachEvent ) {
+                       elem.detachEvent( "on" + type, handle );
+               }
+       };
+
+jQuery.Event = function( src ) {
+       // Allow instantiation without the 'new' keyword
+       if ( !this.preventDefault ) {
+               return new jQuery.Event( src );
+       }
+
+       // Event object
+       if ( src && src.type ) {
+               this.originalEvent = src;
+               this.type = src.type;
+       // Event type
+       } else {
+               this.type = src;
+       }
+
+       // timeStamp is buggy for some events on Firefox(#3843)
+       // So we won't rely on the native value
+       this.timeStamp = jQuery.now();
+
+       // Mark it as fixed
+       this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+       return false;
+}
+function returnTrue() {
+       return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+       preventDefault: function() {
+               this.isDefaultPrevented = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+               
+               // if preventDefault exists run it on the original event
+               if ( e.preventDefault ) {
+                       e.preventDefault();
+
+               // otherwise set the returnValue property of the original event to false (IE)
+               } else {
+                       e.returnValue = false;
+               }
+       },
+       stopPropagation: function() {
+               this.isPropagationStopped = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+               // if stopPropagation exists run it on the original event
+               if ( e.stopPropagation ) {
+                       e.stopPropagation();
+               }
+               // otherwise set the cancelBubble property of the original event to true (IE)
+               e.cancelBubble = true;
+       },
+       stopImmediatePropagation: function() {
+               this.isImmediatePropagationStopped = returnTrue;
+               this.stopPropagation();
+       },
+       isDefaultPrevented: returnFalse,
+       isPropagationStopped: returnFalse,
+       isImmediatePropagationStopped: returnFalse
+};
+
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+       // Check if mouse(over|out) are still within the same parent element
+       var parent = event.relatedTarget;
+
+       // Firefox sometimes assigns relatedTarget a XUL element
+       // which we cannot access the parentNode property of
+       try {
+               // Traverse up the tree
+               while ( parent && parent !== this ) {
+                       parent = parent.parentNode;
+               }
+
+               if ( parent !== this ) {
+                       // set the correct event type
+                       event.type = event.data;
+
+                       // handle event if we actually just moused on to a non sub-element
+                       jQuery.event.handle.apply( this, arguments );
+               }
+
+       // assuming we've left the element since we most likely mousedover a xul element
+       } catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+       event.type = event.data;
+       jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+       mouseenter: "mouseover",
+       mouseleave: "mouseout"
+}, function( orig, fix ) {
+       jQuery.event.special[ orig ] = {
+               setup: function( data ) {
+                       jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+               },
+               teardown: function( data ) {
+                       jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+               }
+       };
+});
+
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+       jQuery.event.special.submit = {
+               setup: function( data, namespaces ) {
+                       if ( this.nodeName.toLowerCase() !== "form" ) {
+                               jQuery.event.add(this, "click.specialSubmit", function( e ) {
+                                       var elem = e.target,
+                                               type = elem.type;
+
+                                       if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+                                               e.liveFired = undefined;
+                                               return trigger( "submit", this, arguments );
+                                       }
+                               });
+        
+                               jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+                                       var elem = e.target,
+                                               type = elem.type;
+
+                                       if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+                                               e.liveFired = undefined;
+                                               return trigger( "submit", this, arguments );
+                                       }
+                               });
+
+                       } else {
+                               return false;
+                       }
+               },
+
+               teardown: function( namespaces ) {
+                       jQuery.event.remove( this, ".specialSubmit" );
+               }
+       };
+
+}
+
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
+
+       var changeFilters,
+
+       getVal = function( elem ) {
+               var type = elem.type, val = elem.value;
+
+               if ( type === "radio" || type === "checkbox" ) {
+                       val = elem.checked;
+
+               } else if ( type === "select-multiple" ) {
+                       val = elem.selectedIndex > -1 ?
+                               jQuery.map( elem.options, function( elem ) {
+                                       return elem.selected;
+                               }).join("-") :
+                               "";
+
+               } else if ( elem.nodeName.toLowerCase() === "select" ) {
+                       val = elem.selectedIndex;
+               }
+
+               return val;
+       },
+
+       testChange = function testChange( e ) {
+               var elem = e.target, data, val;
+
+               if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
+                       return;
+               }
+
+               data = jQuery.data( elem, "_change_data" );
+               val = getVal(elem);
+
+               // the current data will be also retrieved by beforeactivate
+               if ( e.type !== "focusout" || elem.type !== "radio" ) {
+                       jQuery.data( elem, "_change_data", val );
+               }
+               
+               if ( data === undefined || val === data ) {
+                       return;
+               }
+
+               if ( data != null || val ) {
+                       e.type = "change";
+                       e.liveFired = undefined;
+                       return jQuery.event.trigger( e, arguments[1], elem );
+               }
+       };
+
+       jQuery.event.special.change = {
+               filters: {
+                       focusout: testChange, 
+
+                       beforedeactivate: testChange,
+
+                       click: function( e ) {
+                               var elem = e.target, type = elem.type;
+
+                               if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+                                       return testChange.call( this, e );
+                               }
+                       },
+
+                       // Change has to be called before submit
+                       // Keydown will be called before keypress, which is used in submit-event delegation
+                       keydown: function( e ) {
+                               var elem = e.target, type = elem.type;
+
+                               if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+                                       (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+                                       type === "select-multiple" ) {
+                                       return testChange.call( this, e );
+                               }
+                       },
+
+                       // Beforeactivate happens also before the previous element is blurred
+                       // with this event you can't trigger a change event, but you can store
+                       // information
+                       beforeactivate: function( e ) {
+                               var elem = e.target;
+                               jQuery.data( elem, "_change_data", getVal(elem) );
+                       }
+               },
+
+               setup: function( data, namespaces ) {
+                       if ( this.type === "file" ) {
+                               return false;
+                       }
+
+                       for ( var type in changeFilters ) {
+                               jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+                       }
+
+                       return rformElems.test( this.nodeName );
+               },
+
+               teardown: function( namespaces ) {
+                       jQuery.event.remove( this, ".specialChange" );
+
+                       return rformElems.test( this.nodeName );
+               }
+       };
+
+       changeFilters = jQuery.event.special.change.filters;
+
+       // Handle when the input is .focus()'d
+       changeFilters.focus = changeFilters.beforeactivate;
+}
+
+function trigger( type, elem, args ) {
+       args[0].type = type;
+       return jQuery.event.handle.apply( elem, args );
+}
+
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+               jQuery.event.special[ fix ] = {
+                       setup: function() {
+                               if ( focusCounts[fix]++ === 0 ) {
+                                       document.addEventListener( orig, handler, true );
+                               }
+                       }, 
+                       teardown: function() { 
+                               if ( --focusCounts[fix] === 0 ) {
+                                       document.removeEventListener( orig, handler, true );
+                               }
+                       }
+               };
+
+               function handler( e ) { 
+                       e = jQuery.event.fix( e );
+                       e.type = fix;
+                       return jQuery.event.trigger( e, null, e.target );
+               }
+       });
+}
+
+jQuery.each(["bind", "one"], function( i, name ) {
+       jQuery.fn[ name ] = function( type, data, fn ) {
+               // Handle object literals
+               if ( typeof type === "object" ) {
+                       for ( var key in type ) {
+                               this[ name ](key, data, type[key], fn);
+                       }
+                       return this;
+               }
+               
+               if ( jQuery.isFunction( data ) || data === false ) {
+                       fn = data;
+                       data = undefined;
+               }
+
+               var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+                       jQuery( this ).unbind( event, handler );
+                       return fn.apply( this, arguments );
+               }) : fn;
+
+               if ( type === "unload" && name !== "one" ) {
+                       this.one( type, data, fn );
+
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ) {
+                               jQuery.event.add( this[i], type, handler, data );
+                       }
+               }
+
+               return this;
+       };
+});
+
+jQuery.fn.extend({
+       unbind: function( type, fn ) {
+               // Handle object literals
+               if ( typeof type === "object" && !type.preventDefault ) {
+                       for ( var key in type ) {
+                               this.unbind(key, type[key]);
+                       }
+
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ) {
+                               jQuery.event.remove( this[i], type, fn );
+                       }
+               }
+
+               return this;
+       },
+       
+       delegate: function( selector, types, data, fn ) {
+               return this.live( types, data, fn, selector );
+       },
+       
+       undelegate: function( selector, types, fn ) {
+               if ( arguments.length === 0 ) {
+                               return this.unbind( "live" );
+               
+               } else {
+                       return this.die( types, null, fn, selector );
+               }
+       },
+       
+       trigger: function( type, data ) {
+               return this.each(function() {
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+
+       triggerHandler: function( type, data ) {
+               if ( this[0] ) {
+                       var event = jQuery.Event( type );
+                       event.preventDefault();
+                       event.stopPropagation();
+                       jQuery.event.trigger( event, data, this[0] );
+                       return event.result;
+               }
+       },
+
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments,
+                       i = 1;
+
+               // link all the functions, so any of them can unbind this click handler
+               while ( i < args.length ) {
+                       jQuery.proxy( fn, args[ i++ ] );
+               }
+
+               return this.click( jQuery.proxy( fn, function( event ) {
+                       // Figure out which function to execute
+                       var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+                       jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+                       // Make sure that clicks stop
+                       event.preventDefault();
+
+                       // and execute the function
+                       return args[ lastToggle ].apply( this, arguments ) || false;
+               }));
+       },
+
+       hover: function( fnOver, fnOut ) {
+               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+       }
+});
+
+var liveMap = {
+       focus: "focusin",
+       blur: "focusout",
+       mouseenter: "mouseover",
+       mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+       jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+               var type, i = 0, match, namespaces, preType,
+                       selector = origSelector || this.selector,
+                       context = origSelector ? this : jQuery( this.context );
+               
+               if ( typeof types === "object" && !types.preventDefault ) {
+                       for ( var key in types ) {
+                               context[ name ]( key, data, types[key], selector );
+                       }
+                       
+                       return this;
+               }
+
+               if ( jQuery.isFunction( data ) ) {
+                       fn = data;
+                       data = undefined;
+               }
+
+               types = (types || "").split(" ");
+
+               while ( (type = types[ i++ ]) != null ) {
+                       match = rnamespaces.exec( type );
+                       namespaces = "";
+
+                       if ( match )  {
+                               namespaces = match[0];
+                               type = type.replace( rnamespaces, "" );
+                       }
+
+                       if ( type === "hover" ) {
+                               types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+                               continue;
+                       }
+
+                       preType = type;
+
+                       if ( type === "focus" || type === "blur" ) {
+                               types.push( liveMap[ type ] + namespaces );
+                               type = type + namespaces;
+
+                       } else {
+                               type = (liveMap[ type ] || type) + namespaces;
+                       }
+
+                       if ( name === "live" ) {
+                               // bind live handler
+                               for ( var j = 0, l = context.length; j < l; j++ ) {
+                                       jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
+                                               { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+                               }
+
+                       } else {
+                               // unbind live handler
+                               context.unbind( "live." + liveConvert( type, selector ), fn );
+                       }
+               }
+               
+               return this;
+       };
+});
+
+function liveHandler( event ) {
+       var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
+               elems = [],
+               selectors = [],
+               events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
+
+       if ( typeof events === "function" ) {
+               events = events.events;
+       }
+
+       // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+       if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+               return;
+       }
+       
+       if ( event.namespace ) {
+               namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
+       }
+
+       event.liveFired = this;
+
+       var live = events.live.slice(0);
+
+       for ( j = 0; j < live.length; j++ ) {
+               handleObj = live[j];
+
+               if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+                       selectors.push( handleObj.selector );
+
+               } else {
+                       live.splice( j--, 1 );
+               }
+       }
+
+       match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+       for ( i = 0, l = match.length; i < l; i++ ) {
+               close = match[i];
+
+               for ( j = 0; j < live.length; j++ ) {
+                       handleObj = live[j];
+
+                       if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
+                               elem = close.elem;
+                               related = null;
+
+                               // Those two events require additional checking
+                               if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+                                       event.type = handleObj.preType;
+                                       related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+                               }
+
+                               if ( !related || related !== elem ) {
+                                       elems.push({ elem: elem, handleObj: handleObj, level: close.level });
+                               }
+                       }
+               }
+       }
+
+       for ( i = 0, l = elems.length; i < l; i++ ) {
+               match = elems[i];
+
+               if ( maxLevel && match.level > maxLevel ) {
+                       break;
+               }
+
+               event.currentTarget = match.elem;
+               event.data = match.handleObj.data;
+               event.handleObj = match.handleObj;
+
+               ret = match.handleObj.origHandler.apply( match.elem, arguments );
+
+               if ( ret === false || event.isPropagationStopped() ) {
+                       maxLevel = match.level;
+
+                       if ( ret === false ) {
+                               stop = false;
+                       }
+                       if ( event.isImmediatePropagationStopped() ) {
+                               break;
+                       }
+               }
+       }
+
+       return stop;
+}
+
+function liveConvert( type, selector ) {
+       return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+       "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+       // Handle event binding
+       jQuery.fn[ name ] = function( data, fn ) {
+               if ( fn == null ) {
+                       fn = data;
+                       data = null;
+               }
+
+               return arguments.length > 0 ?
+                       this.bind( name, data, fn ) :
+                       this.trigger( name );
+       };
+
+       if ( jQuery.attrFn ) {
+               jQuery.attrFn[ name ] = true;
+       }
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+       jQuery(window).bind("unload", function() {
+               for ( var id in jQuery.cache ) {
+                       if ( jQuery.cache[ id ].handle ) {
+                               // Try/Catch is to handle iframes being unloaded, see #4280
+                               try {
+                                       jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+                               } catch(e) {}
+                       }
+               }
+       });
+}
+
+
+/*!
+ * Sizzle CSS Selector Engine - v1.0
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+       done = 0,
+       toString = Object.prototype.toString,
+       hasDuplicate = false,
+       baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+//   Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+       baseHasDuplicate = false;
+       return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+       results = results || [];
+       context = context || document;
+
+       var origContext = context;
+
+       if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+               return [];
+       }
+       
+       if ( !selector || typeof selector !== "string" ) {
+               return results;
+       }
+
+       var m, set, checkSet, extra, ret, cur, pop, i,
+               prune = true,
+               contextXML = Sizzle.isXML( context ),
+               parts = [],
+               soFar = selector;
+       
+       // Reset the position of the chunker regexp (start from head)
+       do {
+               chunker.exec( "" );
+               m = chunker.exec( soFar );
+
+               if ( m ) {
+                       soFar = m[3];
+               
+                       parts.push( m[1] );
+               
+                       if ( m[2] ) {
+                               extra = m[3];
+                               break;
+                       }
+               }
+       } while ( m );
+
+       if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+               if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+                       set = posProcess( parts[0] + parts[1], context );
+
+               } else {
+                       set = Expr.relative[ parts[0] ] ?
+                               [ context ] :
+                               Sizzle( parts.shift(), context );
+
+                       while ( parts.length ) {
+                               selector = parts.shift();
+
+                               if ( Expr.relative[ selector ] ) {
+                                       selector += parts.shift();
+                               }
+                               
+                               set = posProcess( selector, set );
+                       }
+               }
+
+       } else {
+               // Take a shortcut and set the context if the root selector is an ID
+               // (but not if it'll be faster if the inner selector is an ID)
+               if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+                               Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+                       ret = Sizzle.find( parts.shift(), context, contextXML );
+                       context = ret.expr ?
+                               Sizzle.filter( ret.expr, ret.set )[0] :
+                               ret.set[0];
+               }
+
+               if ( context ) {
+                       ret = seed ?
+                               { expr: parts.pop(), set: makeArray(seed) } :
+                               Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+                       set = ret.expr ?
+                               Sizzle.filter( ret.expr, ret.set ) :
+                               ret.set;
+
+                       if ( parts.length > 0 ) {
+                               checkSet = makeArray( set );
+
+                       } else {
+                               prune = false;
+                       }
+
+                       while ( parts.length ) {
+                               cur = parts.pop();
+                               pop = cur;
+
+                               if ( !Expr.relative[ cur ] ) {
+                                       cur = "";
+                               } else {
+                                       pop = parts.pop();
+                               }
+
+                               if ( pop == null ) {
+                                       pop = context;
+                               }
+
+                               Expr.relative[ cur ]( checkSet, pop, contextXML );
+                       }
+
+               } else {
+                       checkSet = parts = [];
+               }
+       }
+
+       if ( !checkSet ) {
+               checkSet = set;
+       }
+
+       if ( !checkSet ) {
+               Sizzle.error( cur || selector );
+       }
+
+       if ( toString.call(checkSet) === "[object Array]" ) {
+               if ( !prune ) {
+                       results.push.apply( results, checkSet );
+
+               } else if ( context && context.nodeType === 1 ) {
+                       for ( i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+                                       results.push( set[i] );
+                               }
+                       }
+
+               } else {
+                       for ( i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               }
+
+       } else {
+               makeArray( checkSet, results );
+       }
+
+       if ( extra ) {
+               Sizzle( extra, origContext, results, seed );
+               Sizzle.uniqueSort( results );
+       }
+
+       return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+       if ( sortOrder ) {
+               hasDuplicate = baseHasDuplicate;
+               results.sort( sortOrder );
+
+               if ( hasDuplicate ) {
+                       for ( var i = 1; i < results.length; i++ ) {
+                               if ( results[i] === results[ i - 1 ] ) {
+                                       results.splice( i--, 1 );
+                               }
+                       }
+               }
+       }
+
+       return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+       return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+       return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+       var set;
+
+       if ( !expr ) {
+               return [];
+       }
+
+       for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
+               var match,
+                       type = Expr.order[i];
+               
+               if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+                       var left = match[1];
+                       match.splice( 1, 1 );
+
+                       if ( left.substr( left.length - 1 ) !== "\\" ) {
+                               match[1] = (match[1] || "").replace(/\\/g, "");
+                               set = Expr.find[ type ]( match, context, isXML );
+
+                               if ( set != null ) {
+                                       expr = expr.replace( Expr.match[ type ], "" );
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if ( !set ) {
+               set = context.getElementsByTagName( "*" );
+       }
+
+       return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+       var match, anyFound,
+               old = expr,
+               result = [],
+               curLoop = set,
+               isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+       while ( expr && set.length ) {
+               for ( var type in Expr.filter ) {
+                       if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+                               var found, item,
+                                       filter = Expr.filter[ type ],
+                                       left = match[1];
+
+                               anyFound = false;
+
+                               match.splice(1,1);
+
+                               if ( left.substr( left.length - 1 ) === "\\" ) {
+                                       continue;
+                               }
+
+                               if ( curLoop === result ) {
+                                       result = [];
+                               }
+
+                               if ( Expr.preFilter[ type ] ) {
+                                       match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+                                       if ( !match ) {
+                                               anyFound = found = true;
+
+                                       } else if ( match === true ) {
+                                               continue;
+                                       }
+                               }
+
+                               if ( match ) {
+                                       for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
+                                               if ( item ) {
+                                                       found = filter( item, match, i, curLoop );
+                                                       var pass = not ^ !!found;
+
+                                                       if ( inplace && found != null ) {
+                                                               if ( pass ) {
+                                                                       anyFound = true;
+
+                                                               } else {
+                                                                       curLoop[i] = false;
+                                                               }
+
+                                                       } else if ( pass ) {
+                                                               result.push( item );
+                                                               anyFound = true;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if ( found !== undefined ) {
+                                       if ( !inplace ) {
+                                               curLoop = result;
+                                       }
+
+                                       expr = expr.replace( Expr.match[ type ], "" );
+
+                                       if ( !anyFound ) {
+                                               return [];
+                                       }
+
+                                       break;
+                               }
+                       }
+               }
+
+               // Improper expression
+               if ( expr === old ) {
+                       if ( anyFound == null ) {
+                               Sizzle.error( expr );
+
+                       } else {
+                               break;
+                       }
+               }
+
+               old = expr;
+       }
+
+       return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+       throw "Syntax error, unrecognized expression: " + msg;
+};
+
+var Expr = Sizzle.selectors = {
+       order: [ "ID", "NAME", "TAG" ],
+
+       match: {
+               ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+               CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+               NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+               ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+               TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+               CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,
+               POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+               PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+       },
+
+       leftMatch: {},
+
+       attrMap: {
+               "class": "className",
+               "for": "htmlFor"
+       },
+
+       attrHandle: {
+               href: function( elem ) {
+                       return elem.getAttribute( "href" );
+               }
+       },
+
+       relative: {
+               "+": function(checkSet, part){
+                       var isPartStr = typeof part === "string",
+                               isTag = isPartStr && !/\W/.test( part ),
+                               isPartStrNotTag = isPartStr && !isTag;
+
+                       if ( isTag ) {
+                               part = part.toLowerCase();
+                       }
+
+                       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+                               if ( (elem = checkSet[i]) ) {
+                                       while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+                                       checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+                                               elem || false :
+                                               elem === part;
+                               }
+                       }
+
+                       if ( isPartStrNotTag ) {
+                               Sizzle.filter( part, checkSet, true );
+                       }
+               },
+
+               ">": function( checkSet, part ) {
+                       var elem,
+                               isPartStr = typeof part === "string",
+                               i = 0,
+                               l = checkSet.length;
+
+                       if ( isPartStr && !/\W/.test( part ) ) {
+                               part = part.toLowerCase();
+
+                               for ( ; i < l; i++ ) {
+                                       elem = checkSet[i];
+
+                                       if ( elem ) {
+                                               var parent = elem.parentNode;
+                                               checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+                                       }
+                               }
+
+                       } else {
+                               for ( ; i < l; i++ ) {
+                                       elem = checkSet[i];
+
+                                       if ( elem ) {
+                                               checkSet[i] = isPartStr ?
+                                                       elem.parentNode :
+                                                       elem.parentNode === part;
+                                       }
+                               }
+
+                               if ( isPartStr ) {
+                                       Sizzle.filter( part, checkSet, true );
+                               }
+                       }
+               },
+
+               "": function(checkSet, part, isXML){
+                       var nodeCheck,
+                               doneName = done++,
+                               checkFn = dirCheck;
+
+                       if ( typeof part === "string" && !/\W/.test(part) ) {
+                               part = part.toLowerCase();
+                               nodeCheck = part;
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+               },
+
+               "~": function( checkSet, part, isXML ) {
+                       var nodeCheck,
+                               doneName = done++,
+                               checkFn = dirCheck;
+
+                       if ( typeof part === "string" && !/\W/.test( part ) ) {
+                               part = part.toLowerCase();
+                               nodeCheck = part;
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+               }
+       },
+
+       find: {
+               ID: function( match, context, isXML ) {
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               // Check parentNode to catch when Blackberry 4.6 returns
+                               // nodes that are no longer in the document #6963
+                               return m && m.parentNode ? [m] : [];
+                       }
+               },
+
+               NAME: function( match, context ) {
+                       if ( typeof context.getElementsByName !== "undefined" ) {
+                               var ret = [],
+                                       results = context.getElementsByName( match[1] );
+
+                               for ( var i = 0, l = results.length; i < l; i++ ) {
+                                       if ( results[i].getAttribute("name") === match[1] ) {
+                                               ret.push( results[i] );
+                                       }
+                               }
+
+                               return ret.length === 0 ? null : ret;
+                       }
+               },
+
+               TAG: function( match, context ) {
+                       return context.getElementsByTagName( match[1] );
+               }
+       },
+       preFilter: {
+               CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+                       match = " " + match[1].replace(/\\/g, "") + " ";
+
+                       if ( isXML ) {
+                               return match;
+                       }
+
+                       for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+                               if ( elem ) {
+                                       if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+                                               if ( !inplace ) {
+                                                       result.push( elem );
+                                               }
+
+                                       } else if ( inplace ) {
+                                               curLoop[i] = false;
+                                       }
+                               }
+                       }
+
+                       return false;
+               },
+
+               ID: function( match ) {
+                       return match[1].replace(/\\/g, "");
+               },
+
+               TAG: function( match, curLoop ) {
+                       return match[1].toLowerCase();
+               },
+
+               CHILD: function( match ) {
+                       if ( match[1] === "nth" ) {
+                               // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+                               var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
+                                       match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+                                       !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+                               // calculate the numbers (first)n+(last) including if they are negative
+                               match[2] = (test[1] + (test[2] || 1)) - 0;
+                               match[3] = test[3] - 0;
+                       }
+
+                       // TODO: Move to normal caching system
+                       match[0] = done++;
+
+                       return match;
+               },
+
+               ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+                       var name = match[1].replace(/\\/g, "");
+                       
+                       if ( !isXML && Expr.attrMap[name] ) {
+                               match[1] = Expr.attrMap[name];
+                       }
+
+                       if ( match[2] === "~=" ) {
+                               match[4] = " " + match[4] + " ";
+                       }
+
+                       return match;
+               },
+
+               PSEUDO: function( match, curLoop, inplace, result, not ) {
+                       if ( match[1] === "not" ) {
+                               // If we're dealing with a complex expression, or a simple one
+                               if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+                                       match[3] = Sizzle(match[3], null, null, curLoop);
+
+                               } else {
+                                       var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+                                       if ( !inplace ) {
+                                               result.push.apply( result, ret );
+                                       }
+
+                                       return false;
+                               }
+
+                       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+                               return true;
+                       }
+                       
+                       return match;
+               },
+
+               POS: function( match ) {
+                       match.unshift( true );
+
+                       return match;
+               }
+       },
+       
+       filters: {
+               enabled: function( elem ) {
+                       return elem.disabled === false && elem.type !== "hidden";
+               },
+
+               disabled: function( elem ) {
+                       return elem.disabled === true;
+               },
+
+               checked: function( elem ) {
+                       return elem.checked === true;
+               },
+               
+               selected: function( elem ) {
+                       // Accessing this property makes selected-by-default
+                       // options in Safari work properly
+                       elem.parentNode.selectedIndex;
+                       
+                       return elem.selected === true;
+               },
+
+               parent: function( elem ) {
+                       return !!elem.firstChild;
+               },
+
+               empty: function( elem ) {
+                       return !elem.firstChild;
+               },
+
+               has: function( elem, i, match ) {
+                       return !!Sizzle( match[3], elem ).length;
+               },
+
+               header: function( elem ) {
+                       return (/h\d/i).test( elem.nodeName );
+               },
+
+               text: function( elem ) {
+                       return "text" === elem.type;
+               },
+               radio: function( elem ) {
+                       return "radio" === elem.type;
+               },
+
+               checkbox: function( elem ) {
+                       return "checkbox" === elem.type;
+               },
+
+               file: function( elem ) {
+                       return "file" === elem.type;
+               },
+               password: function( elem ) {
+                       return "password" === elem.type;
+               },
+
+               submit: function( elem ) {
+                       return "submit" === elem.type;
+               },
+
+               image: function( elem ) {
+                       return "image" === elem.type;
+               },
+
+               reset: function( elem ) {
+                       return "reset" === elem.type;
+               },
+
+               button: function( elem ) {
+                       return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
+               },
+
+               input: function( elem ) {
+                       return (/input|select|textarea|button/i).test( elem.nodeName );
+               }
+       },
+       setFilters: {
+               first: function( elem, i ) {
+                       return i === 0;
+               },
+
+               last: function( elem, i, match, array ) {
+                       return i === array.length - 1;
+               },
+
+               even: function( elem, i ) {
+                       return i % 2 === 0;
+               },
+
+               odd: function( elem, i ) {
+                       return i % 2 === 1;
+               },
+
+               lt: function( elem, i, match ) {
+                       return i < match[3] - 0;
+               },
+
+               gt: function( elem, i, match ) {
+                       return i > match[3] - 0;
+               },
+
+               nth: function( elem, i, match ) {
+                       return match[3] - 0 === i;
+               },
+
+               eq: function( elem, i, match ) {
+                       return match[3] - 0 === i;
+               }
+       },
+       filter: {
+               PSEUDO: function( elem, match, i, array ) {
+                       var name = match[1],
+                               filter = Expr.filters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+
+                       } else if ( name === "contains" ) {
+                               return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+                       } else if ( name === "not" ) {
+                               var not = match[3];
+
+                               for ( var j = 0, l = not.length; j < l; j++ ) {
+                                       if ( not[j] === elem ) {
+                                               return false;
+                                       }
+                               }
+
+                               return true;
+
+                       } else {
+                               Sizzle.error( "Syntax error, unrecognized expression: " + name );
+                       }
+               },
+
+               CHILD: function( elem, match ) {
+                       var type = match[1],
+                               node = elem;
+
+                       switch ( type ) {
+                               case "only":
+                               case "first":
+                                       while ( (node = node.previousSibling) )  {
+                                               if ( node.nodeType === 1 ) { 
+                                                       return false; 
+                                               }
+                                       }
+
+                                       if ( type === "first" ) { 
+                                               return true; 
+                                       }
+
+                                       node = elem;
+
+                               case "last":
+                                       while ( (node = node.nextSibling) )      {
+                                               if ( node.nodeType === 1 ) { 
+                                                       return false; 
+                                               }
+                                       }
+
+                                       return true;
+
+                               case "nth":
+                                       var first = match[2],
+                                               last = match[3];
+
+                                       if ( first === 1 && last === 0 ) {
+                                               return true;
+                                       }
+                                       
+                                       var doneName = match[0],
+                                               parent = elem.parentNode;
+       
+                                       if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
+                                               var count = 0;
+                                               
+                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {
+                                                       if ( node.nodeType === 1 ) {
+                                                               node.nodeIndex = ++count;
+                                                       }
+                                               } 
+
+                                               parent.sizcache = doneName;
+                                       }
+                                       
+                                       var diff = elem.nodeIndex - last;
+
+                                       if ( first === 0 ) {
+                                               return diff === 0;
+
+                                       } else {
+                                               return ( diff % first === 0 && diff / first >= 0 );
+                                       }
+                       }
+               },
+
+               ID: function( elem, match ) {
+                       return elem.nodeType === 1 && elem.getAttribute("id") === match;
+               },
+
+               TAG: function( elem, match ) {
+                       return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
+               },
+               
+               CLASS: function( elem, match ) {
+                       return (" " + (elem.className || elem.getAttribute("class")) + " ")
+                               .indexOf( match ) > -1;
+               },
+
+               ATTR: function( elem, match ) {
+                       var name = match[1],
+                               result = Expr.attrHandle[ name ] ?
+                                       Expr.attrHandle[ name ]( elem ) :
+                                       elem[ name ] != null ?
+                                               elem[ name ] :
+                                               elem.getAttribute( name ),
+                               value = result + "",
+                               type = match[2],
+                               check = match[4];
+
+                       return result == null ?
+                               type === "!=" :
+                               type === "=" ?
+                               value === check :
+                               type === "*=" ?
+                               value.indexOf(check) >= 0 :
+                               type === "~=" ?
+                               (" " + value + " ").indexOf(check) >= 0 :
+                               !check ?
+                               value && result !== false :
+                               type === "!=" ?
+                               value !== check :
+                               type === "^=" ?
+                               value.indexOf(check) === 0 :
+                               type === "$=" ?
+                               value.substr(value.length - check.length) === check :
+                               type === "|=" ?
+                               value === check || value.substr(0, check.length + 1) === check + "-" :
+                               false;
+               },
+
+               POS: function( elem, match, i, array ) {
+                       var name = match[2],
+                               filter = Expr.setFilters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       }
+               }
+       }
+};
+
+var origPOS = Expr.match.POS,
+       fescape = function(all, num){
+               return "\\" + (num - 0 + 1);
+       };
+
+for ( var type in Expr.match ) {
+       Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+       Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+       array = Array.prototype.slice.call( array, 0 );
+
+       if ( results ) {
+               results.push.apply( results, array );
+               return results;
+       }
+       
+       return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+       Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+       makeArray = function( array, results ) {
+               var i = 0,
+                       ret = results || [];
+
+               if ( toString.call(array) === "[object Array]" ) {
+                       Array.prototype.push.apply( ret, array );
+
+               } else {
+                       if ( typeof array.length === "number" ) {
+                               for ( var l = array.length; i < l; i++ ) {
+                                       ret.push( array[i] );
+                               }
+
+                       } else {
+                               for ( ; array[i]; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       }
+               }
+
+               return ret;
+       };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+       sortOrder = function( a, b ) {
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
+               }
+
+               if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+                       return a.compareDocumentPosition ? -1 : 1;
+               }
+
+               return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+       };
+
+} else {
+       sortOrder = function( a, b ) {
+               var al, bl,
+                       ap = [],
+                       bp = [],
+                       aup = a.parentNode,
+                       bup = b.parentNode,
+                       cur = aup;
+
+               // The nodes are identical, we can exit early
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
+
+               // If the nodes are siblings (or identical) we can do a quick check
+               } else if ( aup === bup ) {
+                       return siblingCheck( a, b );
+
+               // If no parents were found then the nodes are disconnected
+               } else if ( !aup ) {
+                       return -1;
+
+               } else if ( !bup ) {
+                       return 1;
+               }
+
+               // Otherwise they're somewhere else in the tree so we need
+               // to build up a full list of the parentNodes for comparison
+               while ( cur ) {
+                       ap.unshift( cur );
+                       cur = cur.parentNode;
+               }
+
+               cur = bup;
+
+               while ( cur ) {
+                       bp.unshift( cur );
+                       cur = cur.parentNode;
+               }
+
+               al = ap.length;
+               bl = bp.length;
+
+               // Start walking down the tree looking for a discrepancy
+               for ( var i = 0; i < al && i < bl; i++ ) {
+                       if ( ap[i] !== bp[i] ) {
+                               return siblingCheck( ap[i], bp[i] );
+                       }
+               }
+
+               // We ended someplace up the tree so do a sibling check
+               return i === al ?
+                       siblingCheck( a, bp[i], -1 ) :
+                       siblingCheck( ap[i], b, 1 );
+       };
+
+       siblingCheck = function( a, b, ret ) {
+               if ( a === b ) {
+                       return ret;
+               }
+
+               var cur = a.nextSibling;
+
+               while ( cur ) {
+                       if ( cur === b ) {
+                               return -1;
+                       }
+
+                       cur = cur.nextSibling;
+               }
+
+               return 1;
+       };
+}
+
+// Utility function for retreiving the text value of an array of DOM nodes
+Sizzle.getText = function( elems ) {
+       var ret = "", elem;
+
+       for ( var i = 0; elems[i]; i++ ) {
+               elem = elems[i];
+
+               // Get the text from text nodes and CDATA nodes
+               if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+                       ret += elem.nodeValue;
+
+               // Traverse everything else, except comment nodes
+               } else if ( elem.nodeType !== 8 ) {
+                       ret += Sizzle.getText( elem.childNodes );
+               }
+       }
+
+       return ret;
+};
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+       // We're going to inject a fake input element with a specified name
+       var form = document.createElement("div"),
+               id = "script" + (new Date()).getTime(),
+               root = document.documentElement;
+
+       form.innerHTML = "<a name='" + id + "'/>";
+
+       // Inject it into the root element, check its status, and remove it quickly
+       root.insertBefore( form, root.firstChild );
+
+       // The workaround has to do additional checks after a getElementById
+       // Which slows things down for other browsers (hence the branching)
+       if ( document.getElementById( id ) ) {
+               Expr.find.ID = function( match, context, isXML ) {
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+
+                               return m ?
+                                       m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+                                               [m] :
+                                               undefined :
+                                       [];
+                       }
+               };
+
+               Expr.filter.ID = function( elem, match ) {
+                       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+                       return elem.nodeType === 1 && node && node.nodeValue === match;
+               };
+       }
+
+       root.removeChild( form );
+
+       // release memory in IE
+       root = form = null;
+})();
+
+(function(){
+       // Check to see if the browser returns only elements
+       // when doing getElementsByTagName("*")
+
+       // Create a fake element
+       var div = document.createElement("div");
+       div.appendChild( document.createComment("") );
+
+       // Make sure no comments are found
+       if ( div.getElementsByTagName("*").length > 0 ) {
+               Expr.find.TAG = function( match, context ) {
+                       var results = context.getElementsByTagName( match[1] );
+
+                       // Filter out possible comments
+                       if ( match[1] === "*" ) {
+                               var tmp = [];
+
+                               for ( var i = 0; results[i]; i++ ) {
+                                       if ( results[i].nodeType === 1 ) {
+                                               tmp.push( results[i] );
+                                       }
+                               }
+
+                               results = tmp;
+                       }
+
+                       return results;
+               };
+       }
+
+       // Check to see if an attribute returns normalized href attributes
+       div.innerHTML = "<a href='#'></a>";
+
+       if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+                       div.firstChild.getAttribute("href") !== "#" ) {
+
+               Expr.attrHandle.href = function( elem ) {
+                       return elem.getAttribute( "href", 2 );
+               };
+       }
+
+       // release memory in IE
+       div = null;
+})();
+
+if ( document.querySelectorAll ) {
+       (function(){
+               var oldSizzle = Sizzle,
+                       div = document.createElement("div"),
+                       id = "__sizzle__";
+
+               div.innerHTML = "<p class='TEST'></p>";
+
+               // Safari can't handle uppercase or unicode characters when
+               // in quirks mode.
+               if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+                       return;
+               }
+       
+               Sizzle = function( query, context, extra, seed ) {
+                       context = context || document;
+
+                       // Make sure that attribute selectors are quoted
+                       query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+                       // Only use querySelectorAll on non-XML documents
+                       // (ID selectors don't work in non-HTML documents)
+                       if ( !seed && !Sizzle.isXML(context) ) {
+                               if ( context.nodeType === 9 ) {
+                                       try {
+                                               return makeArray( context.querySelectorAll(query), extra );
+                                       } catch(qsaError) {}
+
+                               // qSA works strangely on Element-rooted queries
+                               // We can work around this by specifying an extra ID on the root
+                               // and working up from there (Thanks to Andrew Dupont for the technique)
+                               // IE 8 doesn't work on object elements
+                               } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+                                       var old = context.getAttribute( "id" ),
+                                               nid = old || id;
+
+                                       if ( !old ) {
+                                               context.setAttribute( "id", nid );
+                                       }
+
+                                       try {
+                                               return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra );
+
+                                       } catch(pseudoError) {
+                                       } finally {
+                                               if ( !old ) {
+                                                       context.removeAttribute( "id" );
+                                               }
+                                       }
+                               }
+                       }
+               
+                       return oldSizzle(query, context, extra, seed);
+               };
+
+               for ( var prop in oldSizzle ) {
+                       Sizzle[ prop ] = oldSizzle[ prop ];
+               }
+
+               // release memory in IE
+               div = null;
+       })();
+}
+
+(function(){
+       var html = document.documentElement,
+               matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
+               pseudoWorks = false;
+
+       try {
+               // This should fail with an exception
+               // Gecko does not error, returns false instead
+               matches.call( document.documentElement, "[test!='']:sizzle" );
+       
+       } catch( pseudoError ) {
+               pseudoWorks = true;
+       }
+
+       if ( matches ) {
+               Sizzle.matchesSelector = function( node, expr ) {
+                       // Make sure that attribute selectors are quoted
+                       expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+                       if ( !Sizzle.isXML( node ) ) {
+                               try { 
+                                       if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+                                               return matches.call( node, expr );
+                                       }
+                               } catch(e) {}
+                       }
+
+                       return Sizzle(expr, null, null, [node]).length > 0;
+               };
+       }
+})();
+
+(function(){
+       var div = document.createElement("div");
+
+       div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+       // Opera can't find a second classname (in 9.6)
+       // Also, make sure that getElementsByClassName actually exists
+       if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+               return;
+       }
+
+       // Safari caches class attributes, doesn't catch changes (in 3.2)
+       div.lastChild.className = "e";
+
+       if ( div.getElementsByClassName("e").length === 1 ) {
+               return;
+       }
+       
+       Expr.order.splice(1, 0, "CLASS");
+       Expr.find.CLASS = function( match, context, isXML ) {
+               if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+                       return context.getElementsByClassName(match[1]);
+               }
+       };
+
+       // release memory in IE
+       div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+
+               if ( elem ) {
+                       var match = false;
+
+                       elem = elem[dir];
+
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 && !isXML ){
+                                       elem.sizcache = doneName;
+                                       elem.sizset = i;
+                               }
+
+                               if ( elem.nodeName.toLowerCase() === cur ) {
+                                       match = elem;
+                                       break;
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+
+               if ( elem ) {
+                       var match = false;
+                       
+                       elem = elem[dir];
+
+                       while ( elem ) {
+                               if ( elem.sizcache === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !isXML ) {
+                                               elem.sizcache = doneName;
+                                               elem.sizset = i;
+                                       }
+
+                                       if ( typeof cur !== "string" ) {
+                                               if ( elem === cur ) {
+                                                       match = true;
+                                                       break;
+                                               }
+
+                                       } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+                                               match = elem;
+                                               break;
+                                       }
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+if ( document.documentElement.contains ) {
+       Sizzle.contains = function( a, b ) {
+               return a !== b && (a.contains ? a.contains(b) : true);
+       };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+       Sizzle.contains = function( a, b ) {
+               return !!(a.compareDocumentPosition(b) & 16);
+       };
+
+} else {
+       Sizzle.contains = function() {
+               return false;
+       };
+}
+
+Sizzle.isXML = function( elem ) {
+       // documentElement is verified for cases where it doesn't yet exist
+       // (such as loading iframes in IE - #4833) 
+       var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+       return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context ) {
+       var match,
+               tmpSet = [],
+               later = "",
+               root = context.nodeType ? [context] : context;
+
+       // Position selectors must be done after the filter
+       // And so must :not(positional) so we move all PSEUDOs to the end
+       while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+               later += match[0];
+               selector = selector.replace( Expr.match.PSEUDO, "" );
+       }
+
+       selector = Expr.relative[selector] ? selector + "*" : selector;
+
+       for ( var i = 0, l = root.length; i < l; i++ ) {
+               Sizzle( selector, root[i], tmpSet );
+       }
+
+       return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+       rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+       // Note: This RegExp should be improved, or likely pulled from Sizzle
+       rmultiselector = /,/,
+       isSimple = /^.[^:#\[\.,]*$/,
+       slice = Array.prototype.slice,
+       POS = jQuery.expr.match.POS;
+
+jQuery.fn.extend({
+       find: function( selector ) {
+               var ret = this.pushStack( "", "find", selector ),
+                       length = 0;
+
+               for ( var i = 0, l = this.length; i < l; i++ ) {
+                       length = ret.length;
+                       jQuery.find( selector, this[i], ret );
+
+                       if ( i > 0 ) {
+                               // Make sure that the results are unique
+                               for ( var n = length; n < ret.length; n++ ) {
+                                       for ( var r = 0; r < length; r++ ) {
+                                               if ( ret[r] === ret[n] ) {
+                                                       ret.splice(n--, 1);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return ret;
+       },
+
+       has: function( target ) {
+               var targets = jQuery( target );
+               return this.filter(function() {
+                       for ( var i = 0, l = targets.length; i < l; i++ ) {
+                               if ( jQuery.contains( this, targets[i] ) ) {
+                                       return true;
+                               }
+                       }
+               });
+       },
+
+       not: function( selector ) {
+               return this.pushStack( winnow(this, selector, false), "not", selector);
+       },
+
+       filter: function( selector ) {
+               return this.pushStack( winnow(this, selector, true), "filter", selector );
+       },
+       
+       is: function( selector ) {
+               return !!selector && jQuery.filter( selector, this ).length > 0;
+       },
+
+       closest: function( selectors, context ) {
+               var ret = [], i, l, cur = this[0];
+
+               if ( jQuery.isArray( selectors ) ) {
+                       var match, selector,
+                               matches = {},
+                               level = 1;
+
+                       if ( cur && selectors.length ) {
+                               for ( i = 0, l = selectors.length; i < l; i++ ) {
+                                       selector = selectors[i];
+
+                                       if ( !matches[selector] ) {
+                                               matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
+                                                       jQuery( selector, context || this.context ) :
+                                                       selector;
+                                       }
+                               }
+
+                               while ( cur && cur.ownerDocument && cur !== context ) {
+                                       for ( selector in matches ) {
+                                               match = matches[selector];
+
+                                               if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+                                                       ret.push({ selector: selector, elem: cur, level: level });
+                                               }
+                                       }
+
+                                       cur = cur.parentNode;
+                                       level++;
+                               }
+                       }
+
+                       return ret;
+               }
+
+               var pos = POS.test( selectors ) ? 
+                       jQuery( selectors, context || this.context ) : null;
+
+               for ( i = 0, l = this.length; i < l; i++ ) {
+                       cur = this[i];
+
+                       while ( cur ) {
+                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+                                       ret.push( cur );
+                                       break;
+
+                               } else {
+                                       cur = cur.parentNode;
+                                       if ( !cur || !cur.ownerDocument || cur === context ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               ret = ret.length > 1 ? jQuery.unique(ret) : ret;
+               
+               return this.pushStack( ret, "closest", selectors );
+       },
+       
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+               if ( !elem || typeof elem === "string" ) {
+                       return jQuery.inArray( this[0],
+                               // If it receives a string, the selector is used
+                               // If it receives nothing, the siblings are used
+                               elem ? jQuery( elem ) : this.parent().children() );
+               }
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem.jquery ? elem[0] : elem, this );
+       },
+
+       add: function( selector, context ) {
+               var set = typeof selector === "string" ?
+                               jQuery( selector, context || this.context ) :
+                               jQuery.makeArray( selector ),
+                       all = jQuery.merge( this.get(), set );
+
+               return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+                       all :
+                       jQuery.unique( all ) );
+       },
+
+       andSelf: function() {
+               return this.add( this.prevObject );
+       }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+       return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+       parent: function( elem ) {
+               var parent = elem.parentNode;
+               return parent && parent.nodeType !== 11 ? parent : null;
+       },
+       parents: function( elem ) {
+               return jQuery.dir( elem, "parentNode" );
+       },
+       parentsUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "parentNode", until );
+       },
+       next: function( elem ) {
+               return jQuery.nth( elem, 2, "nextSibling" );
+       },
+       prev: function( elem ) {
+               return jQuery.nth( elem, 2, "previousSibling" );
+       },
+       nextAll: function( elem ) {
+               return jQuery.dir( elem, "nextSibling" );
+       },
+       prevAll: function( elem ) {
+               return jQuery.dir( elem, "previousSibling" );
+       },
+       nextUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "nextSibling", until );
+       },
+       prevUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "previousSibling", until );
+       },
+       siblings: function( elem ) {
+               return jQuery.sibling( elem.parentNode.firstChild, elem );
+       },
+       children: function( elem ) {
+               return jQuery.sibling( elem.firstChild );
+       },
+       contents: function( elem ) {
+               return jQuery.nodeName( elem, "iframe" ) ?
+                       elem.contentDocument || elem.contentWindow.document :
+                       jQuery.makeArray( elem.childNodes );
+       }
+}, function( name, fn ) {
+       jQuery.fn[ name ] = function( until, selector ) {
+               var ret = jQuery.map( this, fn, until );
+               
+               if ( !runtil.test( name ) ) {
+                       selector = until;
+               }
+
+               if ( selector && typeof selector === "string" ) {
+                       ret = jQuery.filter( selector, ret );
+               }
+
+               ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+
+               if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+                       ret = ret.reverse();
+               }
+
+               return this.pushStack( ret, name, slice.call(arguments).join(",") );
+       };
+});
+
+jQuery.extend({
+       filter: function( expr, elems, not ) {
+               if ( not ) {
+                       expr = ":not(" + expr + ")";
+               }
+
+               return elems.length === 1 ?
+                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+                       jQuery.find.matches(expr, elems);
+       },
+       
+       dir: function( elem, dir, until ) {
+               var matched = [],
+                       cur = elem[ dir ];
+
+               while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+                       if ( cur.nodeType === 1 ) {
+                               matched.push( cur );
+                       }
+                       cur = cur[dir];
+               }
+               return matched;
+       },
+
+       nth: function( cur, result, dir, elem ) {
+               result = result || 1;
+               var num = 0;
+
+               for ( ; cur; cur = cur[dir] ) {
+                       if ( cur.nodeType === 1 && ++num === result ) {
+                               break;
+                       }
+               }
+
+               return cur;
+       },
+
+       sibling: function( n, elem ) {
+               var r = [];
+
+               for ( ; n; n = n.nextSibling ) {
+                       if ( n.nodeType === 1 && n !== elem ) {
+                               r.push( n );
+                       }
+               }
+
+               return r;
+       }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+       if ( jQuery.isFunction( qualifier ) ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       var retVal = !!qualifier.call( elem, i, elem );
+                       return retVal === keep;
+               });
+
+       } else if ( qualifier.nodeType ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       return (elem === qualifier) === keep;
+               });
+
+       } else if ( typeof qualifier === "string" ) {
+               var filtered = jQuery.grep(elements, function( elem ) {
+                       return elem.nodeType === 1;
+               });
+
+               if ( isSimple.test( qualifier ) ) {
+                       return jQuery.filter(qualifier, filtered, !keep);
+               } else {
+                       qualifier = jQuery.filter( qualifier, filtered );
+               }
+       }
+
+       return jQuery.grep(elements, function( elem, i ) {
+               return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+       });
+}
+
+
+
+
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+       rleadingWhitespace = /^\s+/,
+       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+       rtagName = /<([\w:]+)/,
+       rtbody = /<tbody/i,
+       rhtml = /<|&#?\w+;/,
+       rnocache = /<(?:script|object|embed|option|style)/i,
+       // checked="checked" or checked (html5)
+       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+       raction = /\=([^="'>\s]+\/)>/g,
+       wrapMap = {
+               option: [ 1, "<select multiple='multiple'>", "</select>" ],
+               legend: [ 1, "<fieldset>", "</fieldset>" ],
+               thead: [ 1, "<table>", "</table>" ],
+               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+               area: [ 1, "<map>", "</map>" ],
+               _default: [ 0, "", "" ]
+       };
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+       wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+       text: function( text ) {
+               if ( jQuery.isFunction(text) ) {
+                       return this.each(function(i) {
+                               var self = jQuery( this );
+
+                               self.text( text.call(this, i, self.text()) );
+                       });
+               }
+
+               if ( typeof text !== "object" && text !== undefined ) {
+                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+               }
+
+               return jQuery.text( this );
+       },
+
+       wrapAll: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapAll( html.call(this, i) );
+                       });
+               }
+
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+                       if ( this[0].parentNode ) {
+                               wrap.insertBefore( this[0] );
+                       }
+
+                       wrap.map(function() {
+                               var elem = this;
+
+                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+                                       elem = elem.firstChild;
+                               }
+
+                               return elem;
+                       }).append(this);
+               }
+
+               return this;
+       },
+
+       wrapInner: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapInner( html.call(this, i) );
+                       });
+               }
+
+               return this.each(function() {
+                       var self = jQuery( this ),
+                               contents = self.contents();
+
+                       if ( contents.length ) {
+                               contents.wrapAll( html );
+
+                       } else {
+                               self.append( html );
+                       }
+               });
+       },
+
+       wrap: function( html ) {
+               return this.each(function() {
+                       jQuery( this ).wrapAll( html );
+               });
+       },
+
+       unwrap: function() {
+               return this.parent().each(function() {
+                       if ( !jQuery.nodeName( this, "body" ) ) {
+                               jQuery( this ).replaceWith( this.childNodes );
+                       }
+               }).end();
+       },
+
+       append: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 ) {
+                               this.appendChild( elem );
+                       }
+               });
+       },
+
+       prepend: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 ) {
+                               this.insertBefore( elem, this.firstChild );
+                       }
+               });
+       },
+
+       before: function() {
+               if ( this[0] && this[0].parentNode ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this );
+                       });
+               } else if ( arguments.length ) {
+                       var set = jQuery(arguments[0]);
+                       set.push.apply( set, this.toArray() );
+                       return this.pushStack( set, "before", arguments );
+               }
+       },
+
+       after: function() {
+               if ( this[0] && this[0].parentNode ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this.nextSibling );
+                       });
+               } else if ( arguments.length ) {
+                       var set = this.pushStack( this, "after", arguments );
+                       set.push.apply( set, jQuery(arguments[0]).toArray() );
+                       return set;
+               }
+       },
+       
+       // keepData is for internal use only--do not document
+       remove: function( selector, keepData ) {
+               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+                       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+                               if ( !keepData && elem.nodeType === 1 ) {
+                                       jQuery.cleanData( elem.getElementsByTagName("*") );
+                                       jQuery.cleanData( [ elem ] );
+                               }
+
+                               if ( elem.parentNode ) {
+                                        elem.parentNode.removeChild( elem );
+                               }
+                       }
+               }
+               
+               return this;
+       },
+
+       empty: function() {
+               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+                       // Remove element nodes and prevent memory leaks
+                       if ( elem.nodeType === 1 ) {
+                               jQuery.cleanData( elem.getElementsByTagName("*") );
+                       }
+
+                       // Remove any remaining nodes
+                       while ( elem.firstChild ) {
+                               elem.removeChild( elem.firstChild );
+                       }
+               }
+               
+               return this;
+       },
+
+       clone: function( events ) {
+               // Do the clone
+               var ret = this.map(function() {
+                       if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+                               // IE copies events bound via attachEvent when
+                               // using cloneNode. Calling detachEvent on the
+                               // clone will also remove the events from the orignal
+                               // In order to get around this, we use innerHTML.
+                               // Unfortunately, this means some modifications to
+                               // attributes in IE that are actually only stored
+                               // as properties will not be copied (such as the
+                               // the name attribute on an input).
+                               var html = this.outerHTML,
+                                       ownerDocument = this.ownerDocument;
+
+                               if ( !html ) {
+                                       var div = ownerDocument.createElement("div");
+                                       div.appendChild( this.cloneNode(true) );
+                                       html = div.innerHTML;
+                               }
+
+                               return jQuery.clean([html.replace(rinlinejQuery, "")
+                                       // Handle the case in IE 8 where action=/test/> self-closes a tag
+                                       .replace(raction, '="$1">')
+                                       .replace(rleadingWhitespace, "")], ownerDocument)[0];
+                       } else {
+                               return this.cloneNode(true);
+                       }
+               });
+
+               // Copy the events from the original to the clone
+               if ( events === true ) {
+                       cloneCopyEvent( this, ret );
+                       cloneCopyEvent( this.find("*"), ret.find("*") );
+               }
+
+               // Return the cloned set
+               return ret;
+       },
+
+       html: function( value ) {
+               if ( value === undefined ) {
+                       return this[0] && this[0].nodeType === 1 ?
+                               this[0].innerHTML.replace(rinlinejQuery, "") :
+                               null;
+
+               // See if we can take a shortcut and just use innerHTML
+               } else if ( typeof value === "string" && !rnocache.test( value ) &&
+                       (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+                       !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+                       value = value.replace(rxhtmlTag, "<$1></$2>");
+
+                       try {
+                               for ( var i = 0, l = this.length; i < l; i++ ) {
+                                       // Remove element nodes and prevent memory leaks
+                                       if ( this[i].nodeType === 1 ) {
+                                               jQuery.cleanData( this[i].getElementsByTagName("*") );
+                                               this[i].innerHTML = value;
+                                       }
+                               }
+
+                       // If using innerHTML throws an exception, use the fallback method
+                       } catch(e) {
+                               this.empty().append( value );
+                       }
+
+               } else if ( jQuery.isFunction( value ) ) {
+                       this.each(function(i){
+                               var self = jQuery( this );
+
+                               self.html( value.call(this, i, self.html()) );
+                       });
+
+               } else {
+                       this.empty().append( value );
+               }
+
+               return this;
+       },
+
+       replaceWith: function( value ) {
+               if ( this[0] && this[0].parentNode ) {
+                       // Make sure that the elements are removed from the DOM before they are inserted
+                       // this can help fix replacing a parent with child elements
+                       if ( jQuery.isFunction( value ) ) {
+                               return this.each(function(i) {
+                                       var self = jQuery(this), old = self.html();
+                                       self.replaceWith( value.call( this, i, old ) );
+                               });
+                       }
+
+                       if ( typeof value !== "string" ) {
+                               value = jQuery( value ).detach();
+                       }
+
+                       return this.each(function() {
+                               var next = this.nextSibling,
+                                       parent = this.parentNode;
+
+                               jQuery( this ).remove();
+
+                               if ( next ) {
+                                       jQuery(next).before( value );
+                               } else {
+                                       jQuery(parent).append( value );
+                               }
+                       });
+               } else {
+                       return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
+               }
+       },
+
+       detach: function( selector ) {
+               return this.remove( selector, true );
+       },
+
+       domManip: function( args, table, callback ) {
+               var results, first, fragment, parent,
+                       value = args[0],
+                       scripts = [];
+
+               // We can't cloneNode fragments that contain checked, in WebKit
+               if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+                       return this.each(function() {
+                               jQuery(this).domManip( args, table, callback, true );
+                       });
+               }
+
+               if ( jQuery.isFunction(value) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               args[0] = value.call(this, i, table ? self.html() : undefined);
+                               self.domManip( args, table, callback );
+                       });
+               }
+
+               if ( this[0] ) {
+                       parent = value && value.parentNode;
+
+                       // If we're in a fragment, just use that instead of building a new one
+                       if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+                               results = { fragment: parent };
+
+                       } else {
+                               results = jQuery.buildFragment( args, this, scripts );
+                       }
+                       
+                       fragment = results.fragment;
+                       
+                       if ( fragment.childNodes.length === 1 ) {
+                               first = fragment = fragment.firstChild;
+                       } else {
+                               first = fragment.firstChild;
+                       }
+
+                       if ( first ) {
+                               table = table && jQuery.nodeName( first, "tr" );
+
+                               for ( var i = 0, l = this.length; i < l; i++ ) {
+                                       callback.call(
+                                               table ?
+                                                       root(this[i], first) :
+                                                       this[i],
+                                               i > 0 || results.cacheable || this.length > 1  ?
+                                                       fragment.cloneNode(true) :
+                                                       fragment
+                                       );
+                               }
+                       }
+
+                       if ( scripts.length ) {
+                               jQuery.each( scripts, evalScript );
+                       }
+               }
+
+               return this;
+       }
+});
+
+function root( elem, cur ) {
+       return jQuery.nodeName(elem, "table") ?
+               (elem.getElementsByTagName("tbody")[0] ||
+               elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+               elem;
+}
+
+function cloneCopyEvent(orig, ret) {
+       var i = 0;
+
+       ret.each(function() {
+               if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+                       return;
+               }
+
+               var oldData = jQuery.data( orig[i++] ),
+                       curData = jQuery.data( this, oldData ),
+                       events = oldData && oldData.events;
+
+               if ( events ) {
+                       delete curData.handle;
+                       curData.events = {};
+
+                       for ( var type in events ) {
+                               for ( var handler in events[ type ] ) {
+                                       jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+                               }
+                       }
+               }
+       });
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+       var fragment, cacheable, cacheresults,
+               doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+       // Only cache "small" (1/2 KB) strings that are associated with the main document
+       // Cloning options loses the selected state, so don't cache them
+       // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+       // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+       if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+               !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+               cacheable = true;
+               cacheresults = jQuery.fragments[ args[0] ];
+               if ( cacheresults ) {
+                       if ( cacheresults !== 1 ) {
+                               fragment = cacheresults;
+                       }
+               }
+       }
+
+       if ( !fragment ) {
+               fragment = doc.createDocumentFragment();
+               jQuery.clean( args, doc, fragment, scripts );
+       }
+
+       if ( cacheable ) {
+               jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
+       }
+
+       return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function( name, original ) {
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = [],
+                       insert = jQuery( selector ),
+                       parent = this.length === 1 && this[0].parentNode;
+               
+               if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+                       insert[ original ]( this[0] );
+                       return this;
+                       
+               } else {
+                       for ( var i = 0, l = insert.length; i < l; i++ ) {
+                               var elems = (i > 0 ? this.clone(true) : this).get();
+                               jQuery( insert[i] )[ original ]( elems );
+                               ret = ret.concat( elems );
+                       }
+               
+                       return this.pushStack( ret, name, insert.selector );
+               }
+       };
+});
+
+jQuery.extend({
+       clean: function( elems, context, fragment, scripts ) {
+               context = context || document;
+
+               // !context.createElement fails in IE with an error but returns typeof 'object'
+               if ( typeof context.createElement === "undefined" ) {
+                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+               }
+
+               var ret = [];
+
+               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+                       if ( typeof elem === "number" ) {
+                               elem += "";
+                       }
+
+                       if ( !elem ) {
+                               continue;
+                       }
+
+                       // Convert html string into DOM nodes
+                       if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+                               elem = context.createTextNode( elem );
+
+                       } else if ( typeof elem === "string" ) {
+                               // Fix "XHTML"-style tags in all browsers
+                               elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+                               // Trim whitespace, otherwise indexOf won't work as expected
+                               var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+                                       wrap = wrapMap[ tag ] || wrapMap._default,
+                                       depth = wrap[0],
+                                       div = context.createElement("div");
+
+                               // Go to html and back, then peel off extra wrappers
+                               div.innerHTML = wrap[1] + elem + wrap[2];
+
+                               // Move to the right depth
+                               while ( depth-- ) {
+                                       div = div.lastChild;
+                               }
+
+                               // Remove IE's autoinserted <tbody> from table fragments
+                               if ( !jQuery.support.tbody ) {
+
+                                       // String was a <table>, *may* have spurious <tbody>
+                                       var hasBody = rtbody.test(elem),
+                                               tbody = tag === "table" && !hasBody ?
+                                                       div.firstChild && div.firstChild.childNodes :
+
+                                                       // String was a bare <thead> or <tfoot>
+                                                       wrap[1] === "<table>" && !hasBody ?
+                                                               div.childNodes :
+                                                               [];
+
+                                       for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+                                               if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+                                                       tbody[ j ].parentNode.removeChild( tbody[ j ] );
+                                               }
+                                       }
+
+                               }
+
+                               // IE completely kills leading whitespace when innerHTML is used
+                               if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+                                       div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+                               }
+
+                               elem = div.childNodes;
+                       }
+
+                       if ( elem.nodeType ) {
+                               ret.push( elem );
+                       } else {
+                               ret = jQuery.merge( ret, elem );
+                       }
+               }
+
+               if ( fragment ) {
+                       for ( i = 0; ret[i]; i++ ) {
+                               if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+                               
+                               } else {
+                                       if ( ret[i].nodeType === 1 ) {
+                                               ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+                                       }
+                                       fragment.appendChild( ret[i] );
+                               }
+                       }
+               }
+
+               return ret;
+       },
+       
+       cleanData: function( elems ) {
+               var data, id, cache = jQuery.cache,
+                       special = jQuery.event.special,
+                       deleteExpando = jQuery.support.deleteExpando;
+               
+               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+                       if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+                               continue;
+                       }
+
+                       id = elem[ jQuery.expando ];
+                       
+                       if ( id ) {
+                               data = cache[ id ];
+                               
+                               if ( data && data.events ) {
+                                       for ( var type in data.events ) {
+                                               if ( special[ type ] ) {
+                                                       jQuery.event.remove( elem, type );
+
+                                               } else {
+                                                       jQuery.removeEvent( elem, type, data.handle );
+                                               }
+                                       }
+                               }
+                               
+                               if ( deleteExpando ) {
+                                       delete elem[ jQuery.expando ];
+
+                               } else if ( elem.removeAttribute ) {
+                                       elem.removeAttribute( jQuery.expando );
+                               }
+                               
+                               delete cache[ id ];
+                       }
+               }
+       }
+});
+
+function evalScript( i, elem ) {
+       if ( elem.src ) {
+               jQuery.ajax({
+                       url: elem.src,
+                       async: false,
+                       dataType: "script"
+               });
+       } else {
+               jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+       }
+
+       if ( elem.parentNode ) {
+               elem.parentNode.removeChild( elem );
+       }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+       ropacity = /opacity=([^)]*)/,
+       rdashAlpha = /-([a-z])/ig,
+       rupper = /([A-Z])/g,
+       rnumpx = /^-?\d+(?:px)?$/i,
+       rnum = /^-?\d/,
+
+       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+       cssWidth = [ "Left", "Right" ],
+       cssHeight = [ "Top", "Bottom" ],
+       curCSS,
+
+       getComputedStyle,
+       currentStyle,
+
+       fcamelCase = function( all, letter ) {
+               return letter.toUpperCase();
+       };
+
+jQuery.fn.css = function( name, value ) {
+       // Setting 'undefined' is a no-op
+       if ( arguments.length === 2 && value === undefined ) {
+               return this;
+       }
+
+       return jQuery.access( this, name, value, true, function( elem, name, value ) {
+               return value !== undefined ?
+                       jQuery.style( elem, name, value ) :
+                       jQuery.css( elem, name );
+       });
+};
+
+jQuery.extend({
+       // Add in style property hooks for overriding the default
+       // behavior of getting and setting a style property
+       cssHooks: {
+               opacity: {
+                       get: function( elem, computed ) {
+                               if ( computed ) {
+                                       // We should always get a number back from opacity
+                                       var ret = curCSS( elem, "opacity", "opacity" );
+                                       return ret === "" ? "1" : ret;
+
+                               } else {
+                                       return elem.style.opacity;
+                               }
+                       }
+               }
+       },
+
+       // Exclude the following css properties to add px
+       cssNumber: {
+               "zIndex": true,
+               "fontWeight": true,
+               "opacity": true,
+               "zoom": true,
+               "lineHeight": true
+       },
+
+       // Add in properties whose names you wish to fix before
+       // setting or getting the value
+       cssProps: {
+               // normalize float css property
+               "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+       },
+
+       // Get and set the style property on a DOM Node
+       style: function( elem, name, value, extra ) {
+               // Don't set styles on text and comment nodes
+               if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+                       return;
+               }
+
+               // Make sure that we're working with the right name
+               var ret, origName = jQuery.camelCase( name ),
+                       style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+               name = jQuery.cssProps[ origName ] || origName;
+
+               // Check if we're setting a value
+               if ( value !== undefined ) {
+                       // Make sure that NaN and null values aren't set. See: #7116
+                       if ( typeof value === "number" && isNaN( value ) || value == null ) {
+                               return;
+                       }
+
+                       // If a number was passed in, add 'px' to the (except for certain CSS properties)
+                       if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
+                               value += "px";
+                       }
+
+                       // If a hook was provided, use that value, otherwise just set the specified value
+                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+                               // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+                               // Fixes bug #5509
+                               try {
+                                       style[ name ] = value;
+                               } catch(e) {}
+                       }
+
+               } else {
+                       // If a hook was provided get the non-computed value from there
+                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+                               return ret;
+                       }
+
+                       // Otherwise just get the value from the style object
+                       return style[ name ];
+               }
+       },
+
+       css: function( elem, name, extra ) {
+               // Make sure that we're working with the right name
+               var ret, origName = jQuery.camelCase( name ),
+                       hooks = jQuery.cssHooks[ origName ];
+
+               name = jQuery.cssProps[ origName ] || origName;
+
+               // If a hook was provided get the computed value from there
+               if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+                       return ret;
+
+               // Otherwise, if a way to get the computed value exists, use that
+               } else if ( curCSS ) {
+                       return curCSS( elem, name, origName );
+               }
+       },
+
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var old = {};
+
+               // Remember the old values, and insert the new ones
+               for ( var name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+
+               callback.call( elem );
+
+               // Revert the old values
+               for ( name in options ) {
+                       elem.style[ name ] = old[ name ];
+               }
+       },
+
+       camelCase: function( string ) {
+               return string.replace( rdashAlpha, fcamelCase );
+       }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+       jQuery.cssHooks[ name ] = {
+               get: function( elem, computed, extra ) {
+                       var val;
+
+                       if ( computed ) {
+                               if ( elem.offsetWidth !== 0 ) {
+                                       val = getWH( elem, name, extra );
+
+                               } else {
+                                       jQuery.swap( elem, cssShow, function() {
+                                               val = getWH( elem, name, extra );
+                                       });
+                               }
+
+                               if ( val <= 0 ) {
+                                       val = curCSS( elem, name, name );
+
+                                       if ( val === "0px" && currentStyle ) {
+                                               val = currentStyle( elem, name, name );
+                                       }
+
+                                       if ( val != null ) {
+                                               // Should return "auto" instead of 0, use 0 for
+                                               // temporary backwards-compat
+                                               return val === "" || val === "auto" ? "0px" : val;
+                                       }
+                               }
+
+                               if ( val < 0 || val == null ) {
+                                       val = elem.style[ name ];
+
+                                       // Should return "auto" instead of 0, use 0 for
+                                       // temporary backwards-compat
+                                       return val === "" || val === "auto" ? "0px" : val;
+                               }
+
+                               return typeof val === "string" ? val : val + "px";
+                       }
+               },
+
+               set: function( elem, value ) {
+                       if ( rnumpx.test( value ) ) {
+                               // ignore negative width and height values #1599
+                               value = parseFloat(value);
+
+                               if ( value >= 0 ) {
+                                       return value + "px";
+                               }
+
+                       } else {
+                               return value;
+                       }
+               }
+       };
+});
+
+if ( !jQuery.support.opacity ) {
+       jQuery.cssHooks.opacity = {
+               get: function( elem, computed ) {
+                       // IE uses filters for opacity
+                       return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
+                               (parseFloat(RegExp.$1) / 100) + "" :
+                               computed ? "1" : "";
+               },
+
+               set: function( elem, value ) {
+                       var style = elem.style;
+
+                       // IE has trouble with opacity if it does not have layout
+                       // Force it by setting the zoom level
+                       style.zoom = 1;
+
+                       // Set the alpha filter to set the opacity
+                       var opacity = jQuery.isNaN(value) ?
+                               "" :
+                               "alpha(opacity=" + value * 100 + ")",
+                               filter = style.filter || "";
+
+                       style.filter = ralpha.test(filter) ?
+                               filter.replace(ralpha, opacity) :
+                               style.filter + ' ' + opacity;
+               }
+       };
+}
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+       getComputedStyle = function( elem, newName, name ) {
+               var ret, defaultView, computedStyle;
+
+               name = name.replace( rupper, "-$1" ).toLowerCase();
+
+               if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+                       return undefined;
+               }
+
+               if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+                       ret = computedStyle.getPropertyValue( name );
+                       if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+                               ret = jQuery.style( elem, name );
+                       }
+               }
+
+               return ret;
+       };
+}
+
+if ( document.documentElement.currentStyle ) {
+       currentStyle = function( elem, name ) {
+               var left, rsLeft,
+                       ret = elem.currentStyle && elem.currentStyle[ name ],
+                       style = elem.style;
+
+               // From the awesome hack by Dean Edwards
+               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+               // If we're not dealing with a regular pixel number
+               // but a number that has a weird ending, we need to convert it to pixels
+               if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+                       // Remember the original values
+                       left = style.left;
+                       rsLeft = elem.runtimeStyle.left;
+
+                       // Put in the new values to get a computed value out
+                       elem.runtimeStyle.left = elem.currentStyle.left;
+                       style.left = name === "fontSize" ? "1em" : (ret || 0);
+                       ret = style.pixelLeft + "px";
+
+                       // Revert the changed values
+                       style.left = left;
+                       elem.runtimeStyle.left = rsLeft;
+               }
+
+               return ret === "" ? "auto" : ret;
+       };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+       var which = name === "width" ? cssWidth : cssHeight,
+               val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+       if ( extra === "border" ) {
+               return val;
+       }
+
+       jQuery.each( which, function() {
+               if ( !extra ) {
+                       val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
+               }
+
+               if ( extra === "margin" ) {
+                       val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
+
+               } else {
+                       val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
+               }
+       });
+
+       return val;
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.hidden = function( elem ) {
+               var width = elem.offsetWidth,
+                       height = elem.offsetHeight;
+
+               return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
+       };
+
+       jQuery.expr.filters.visible = function( elem ) {
+               return !jQuery.expr.filters.hidden( elem );
+       };
+}
+
+
+
+
+var jsc = jQuery.now(),
+       rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+       rselectTextarea = /^(?:select|textarea)/i,
+       rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+       rnoContent = /^(?:GET|HEAD)$/,
+       rbracket = /\[\]$/,
+       jsre = /\=\?(&|$)/,
+       rquery = /\?/,
+       rts = /([?&])_=[^&]*/,
+       rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+       r20 = /%20/g,
+       rhash = /#.*$/,
+
+       // Keep a copy of the old load method
+       _load = jQuery.fn.load;
+
+jQuery.fn.extend({
+       load: function( url, params, callback ) {
+               if ( typeof url !== "string" && _load ) {
+                       return _load.apply( this, arguments );
+
+               // Don't do a request if no elements are being requested
+               } else if ( !this.length ) {
+                       return this;
+               }
+
+               var off = url.indexOf(" ");
+               if ( off >= 0 ) {
+                       var selector = url.slice(off, url.length);
+                       url = url.slice(0, off);
+               }
+
+               // Default to a GET request
+               var type = "GET";
+
+               // If the second parameter was provided
+               if ( params ) {
+                       // If it's a function
+                       if ( jQuery.isFunction( params ) ) {
+                               // We assume that it's the callback
+                               callback = params;
+                               params = null;
+
+                       // Otherwise, build a param string
+                       } else if ( typeof params === "object" ) {
+                               params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+                               type = "POST";
+                       }
+               }
+
+               var self = this;
+
+               // Request the remote document
+               jQuery.ajax({
+                       url: url,
+                       type: type,
+                       dataType: "html",
+                       data: params,
+                       complete: function( res, status ) {
+                               // If successful, inject the HTML into all the matched elements
+                               if ( status === "success" || status === "notmodified" ) {
+                                       // See if a selector was specified
+                                       self.html( selector ?
+                                               // Create a dummy div to hold the results
+                                               jQuery("<div>")
+                                                       // inject the contents of the document in, removing the scripts
+                                                       // to avoid any 'Permission Denied' errors in IE
+                                                       .append(res.responseText.replace(rscript, ""))
+
+                                                       // Locate the specified elements
+                                                       .find(selector) :
+
+                                               // If not, just inject the full result
+                                               res.responseText );
+                               }
+
+                               if ( callback ) {
+                                       self.each( callback, [res.responseText, status, res] );
+                               }
+                       }
+               });
+
+               return this;
+       },
+
+       serialize: function() {
+               return jQuery.param(this.serializeArray());
+       },
+
+       serializeArray: function() {
+               return this.map(function() {
+                       return this.elements ? jQuery.makeArray(this.elements) : this;
+               })
+               .filter(function() {
+                       return this.name && !this.disabled &&
+                               (this.checked || rselectTextarea.test(this.nodeName) ||
+                                       rinput.test(this.type));
+               })
+               .map(function( i, elem ) {
+                       var val = jQuery(this).val();
+
+                       return val == null ?
+                               null :
+                               jQuery.isArray(val) ?
+                                       jQuery.map( val, function( val, i ) {
+                                               return { name: elem.name, value: val };
+                                       }) :
+                                       { name: elem.name, value: val };
+               }).get();
+       }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
+       jQuery.fn[o] = function( f ) {
+               return this.bind(o, f);
+       };
+});
+
+jQuery.extend({
+       get: function( url, data, callback, type ) {
+               // shift arguments if data argument was omited
+               if ( jQuery.isFunction( data ) ) {
+                       type = type || callback;
+                       callback = data;
+                       data = null;
+               }
+
+               return jQuery.ajax({
+                       type: "GET",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       getScript: function( url, callback ) {
+               return jQuery.get(url, null, callback, "script");
+       },
+
+       getJSON: function( url, data, callback ) {
+               return jQuery.get(url, data, callback, "json");
+       },
+
+       post: function( url, data, callback, type ) {
+               // shift arguments if data argument was omited
+               if ( jQuery.isFunction( data ) ) {
+                       type = type || callback;
+                       callback = data;
+                       data = {};
+               }
+
+               return jQuery.ajax({
+                       type: "POST",
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       },
+
+       ajaxSetup: function( settings ) {
+               jQuery.extend( jQuery.ajaxSettings, settings );
+       },
+
+       ajaxSettings: {
+               url: location.href,
+               global: true,
+               type: "GET",
+               contentType: "application/x-www-form-urlencoded",
+               processData: true,
+               async: true,
+               /*
+               timeout: 0,
+               data: null,
+               username: null,
+               password: null,
+               traditional: false,
+               */
+               // This function can be overriden by calling jQuery.ajaxSetup
+               xhr: function() {
+                       return new window.XMLHttpRequest();
+               },
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       script: "text/javascript, application/javascript",
+                       json: "application/json, text/javascript",
+                       text: "text/plain",
+                       _default: "*/*"
+               }
+       },
+
+       ajax: function( origSettings ) {
+               var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+                       jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
+
+               s.url = s.url.replace( rhash, "" );
+
+               // Use original (not extended) context object if it was provided
+               s.context = origSettings && origSettings.context != null ? origSettings.context : s;
+
+               // convert data if not already a string
+               if ( s.data && s.processData && typeof s.data !== "string" ) {
+                       s.data = jQuery.param( s.data, s.traditional );
+               }
+
+               // Handle JSONP Parameter Callbacks
+               if ( s.dataType === "jsonp" ) {
+                       if ( type === "GET" ) {
+                               if ( !jsre.test( s.url ) ) {
+                                       s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+                               }
+                       } else if ( !s.data || !jsre.test(s.data) ) {
+                               s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+                       }
+                       s.dataType = "json";
+               }
+
+               // Build temporary JSONP function
+               if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+                       jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+                       // Replace the =? sequence both in the query string and the data
+                       if ( s.data ) {
+                               s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+                       }
+
+                       s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+                       // We need to make sure
+                       // that a JSONP style response is executed properly
+                       s.dataType = "script";
+
+                       // Handle JSONP-style loading
+                       var customJsonp = window[ jsonp ];
+
+                       window[ jsonp ] = function( tmp ) {
+                               if ( jQuery.isFunction( customJsonp ) ) {
+                                       customJsonp( tmp );
+
+                               } else {
+                                       // Garbage collect
+                                       window[ jsonp ] = undefined;
+
+                                       try {
+                                               delete window[ jsonp ];
+                                       } catch( jsonpError ) {}
+                               }
+
+                               data = tmp;
+                               jQuery.handleSuccess( s, xhr, status, data );
+                               jQuery.handleComplete( s, xhr, status, data );
+                               
+                               if ( head ) {
+                                       head.removeChild( script );
+                               }
+                       };
+               }
+
+               if ( s.dataType === "script" && s.cache === null ) {
+                       s.cache = false;
+               }
+
+               if ( s.cache === false && noContent ) {
+                       var ts = jQuery.now();
+
+                       // try replacing _= if it is there
+                       var ret = s.url.replace(rts, "$1_=" + ts);
+
+                       // if nothing was replaced, add timestamp to the end
+                       s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
+               }
+
+               // If data is available, append data to url for GET/HEAD requests
+               if ( s.data && noContent ) {
+                       s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
+               }
+
+               // Watch for a new set of requests
+               if ( s.global && jQuery.active++ === 0 ) {
+                       jQuery.event.trigger( "ajaxStart" );
+               }
+
+               // Matches an absolute URL, and saves the domain
+               var parts = rurl.exec( s.url ),
+                       remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host);
+
+               // If we're requesting a remote document
+               // and trying to load JSON or Script with a GET
+               if ( s.dataType === "script" && type === "GET" && remote ) {
+                       var head = document.getElementsByTagName("head")[0] || document.documentElement;
+                       var script = document.createElement("script");
+                       if ( s.scriptCharset ) {
+                               script.charset = s.scriptCharset;
+                       }
+                       script.src = s.url;
+
+                       // Handle Script loading
+                       if ( !jsonp ) {
+                               var done = false;
+
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function() {
+                                       if ( !done && (!this.readyState ||
+                                                       this.readyState === "loaded" || this.readyState === "complete") ) {
+                                               done = true;
+                                               jQuery.handleSuccess( s, xhr, status, data );
+                                               jQuery.handleComplete( s, xhr, status, data );
+
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
+                                               if ( head && script.parentNode ) {
+                                                       head.removeChild( script );
+                                               }
+                                       }
+                               };
+                       }
+
+                       // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                       // This arises when a base node is used (#2709 and #4378).
+                       head.insertBefore( script, head.firstChild );
+
+                       // We handle everything using the script element injection
+                       return undefined;
+               }
+
+               var requestDone = false;
+
+               // Create the request object
+               var xhr = s.xhr();
+
+               if ( !xhr ) {
+                       return;
+               }
+
+               // Open the socket
+               // Passing null username, generates a login popup on Opera (#2865)
+               if ( s.username ) {
+                       xhr.open(type, s.url, s.async, s.username, s.password);
+               } else {
+                       xhr.open(type, s.url, s.async);
+               }
+
+               // Need an extra try/catch for cross domain requests in Firefox 3
+               try {
+                       // Set content-type if data specified and content-body is valid for this type
+                       if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
+                               xhr.setRequestHeader("Content-Type", s.contentType);
+                       }
+
+                       // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+                       if ( s.ifModified ) {
+                               if ( jQuery.lastModified[s.url] ) {
+                                       xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+                               }
+
+                               if ( jQuery.etag[s.url] ) {
+                                       xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+                               }
+                       }
+
+                       // Set header so the called script knows that it's an XMLHttpRequest
+                       // Only send the header if it's not a remote XHR
+                       if ( !remote ) {
+                               xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+                       }
+
+                       // Set the Accepts header for the server, depending on the dataType
+                       xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
+                               s.accepts[ s.dataType ] + ", */*; q=0.01" :
+                               s.accepts._default );
+               } catch( headerError ) {}
+
+               // Allow custom headers/mimetypes and early abort
+               if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) {
+                       // Handle the global AJAX counter
+                       if ( s.global && jQuery.active-- === 1 ) {
+                               jQuery.event.trigger( "ajaxStop" );
+                       }
+
+                       // close opended socket
+                       xhr.abort();
+                       return false;
+               }
+
+               if ( s.global ) {
+                       jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] );
+               }
+
+               // Wait for a response to come back
+               var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+                       // The request was aborted
+                       if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+                               // Opera doesn't call onreadystatechange before this point
+                               // so we simulate the call
+                               if ( !requestDone ) {
+                                       jQuery.handleComplete( s, xhr, status, data );
+                               }
+
+                               requestDone = true;
+                               if ( xhr ) {
+                                       xhr.onreadystatechange = jQuery.noop;
+                               }
+
+                       // The transfer is complete and the data is available, or the request timed out
+                       } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
+                               requestDone = true;
+                               xhr.onreadystatechange = jQuery.noop;
+
+                               status = isTimeout === "timeout" ?
+                                       "timeout" :
+                                       !jQuery.httpSuccess( xhr ) ?
+                                               "error" :
+                                               s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+                                                       "notmodified" :
+                                                       "success";
+
+                               var errMsg;
+
+                               if ( status === "success" ) {
+                                       // Watch for, and catch, XML document parse errors
+                                       try {
+                                               // process the data (runs the xml through httpData regardless of callback)
+                                               data = jQuery.httpData( xhr, s.dataType, s );
+                                       } catch( parserError ) {
+                                               status = "parsererror";
+                                               errMsg = parserError;
+                                       }
+                               }
+
+                               // Make sure that the request was successful or notmodified
+                               if ( status === "success" || status === "notmodified" ) {
+                                       // JSONP handles its own success callback
+                                       if ( !jsonp ) {
+                                               jQuery.handleSuccess( s, xhr, status, data );
+                                       }
+                               } else {
+                                       jQuery.handleError( s, xhr, status, errMsg );
+                               }
+
+                               // Fire the complete handlers
+                               if ( !jsonp ) {
+                                       jQuery.handleComplete( s, xhr, status, data );
+                               }
+
+                               if ( isTimeout === "timeout" ) {
+                                       xhr.abort();
+                               }
+
+                               // Stop memory leaks
+                               if ( s.async ) {
+                                       xhr = null;
+                               }
+                       }
+               };
+
+               // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
+               // Opera doesn't fire onreadystatechange at all on abort
+               try {
+                       var oldAbort = xhr.abort;
+                       xhr.abort = function() {
+                               if ( xhr ) {
+                                       // oldAbort has no call property in IE7 so
+                                       // just do it this way, which works in all
+                                       // browsers
+                                       Function.prototype.call.call( oldAbort, xhr );
+                               }
+
+                               onreadystatechange( "abort" );
+                       };
+               } catch( abortError ) {}
+
+               // Timeout checker
+               if ( s.async && s.timeout > 0 ) {
+                       setTimeout(function() {
+                               // Check to see if the request is still happening
+                               if ( xhr && !requestDone ) {
+                                       onreadystatechange( "timeout" );
+                               }
+                       }, s.timeout);
+               }
+
+               // Send the data
+               try {
+                       xhr.send( noContent || s.data == null ? null : s.data );
+
+               } catch( sendError ) {
+                       jQuery.handleError( s, xhr, null, sendError );
+
+                       // Fire the complete handlers
+                       jQuery.handleComplete( s, xhr, status, data );
+               }
+
+               // firefox 1.5 doesn't fire statechange for sync requests
+               if ( !s.async ) {
+                       onreadystatechange();
+               }
+
+               // return XMLHttpRequest to allow aborting the request etc.
+               return xhr;
+       },
+
+       // Serialize an array of form elements or a set of
+       // key/values into a query string
+       param: function( a, traditional ) {
+               var s = [],
+                       add = function( key, value ) {
+                               // If value is a function, invoke it and return its value
+                               value = jQuery.isFunction(value) ? value() : value;
+                               s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+                       };
+               
+               // Set traditional to true for jQuery <= 1.3.2 behavior.
+               if ( traditional === undefined ) {
+                       traditional = jQuery.ajaxSettings.traditional;
+               }
+               
+               // If an array was passed in, assume that it is an array of form elements.
+               if ( jQuery.isArray(a) || a.jquery ) {
+                       // Serialize the form elements
+                       jQuery.each( a, function() {
+                               add( this.name, this.value );
+                       });
+                       
+               } else {
+                       // If traditional, encode the "old" way (the way 1.3.2 or older
+                       // did it), otherwise encode params recursively.
+                       for ( var prefix in a ) {
+                               buildParams( prefix, a[prefix], traditional, add );
+                       }
+               }
+
+               // Return the resulting serialization
+               return s.join("&").replace(r20, "+");
+       }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+       if ( jQuery.isArray(obj) && obj.length ) {
+               // Serialize array item.
+               jQuery.each( obj, function( i, v ) {
+                       if ( traditional || rbracket.test( prefix ) ) {
+                               // Treat each array item as a scalar.
+                               add( prefix, v );
+
+                       } else {
+                               // If array item is non-scalar (array or object), encode its
+                               // numeric index to resolve deserialization ambiguity issues.
+                               // Note that rack (as of 1.0.0) can't currently deserialize
+                               // nested arrays properly, and attempting to do so may cause
+                               // a server error. Possible fixes are to modify rack's
+                               // deserialization algorithm or to provide an option or flag
+                               // to force array serialization to be shallow.
+                               buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+                       }
+               });
+                       
+       } else if ( !traditional && obj != null && typeof obj === "object" ) {
+               if ( jQuery.isEmptyObject( obj ) ) {
+                       add( prefix, "" );
+
+               // Serialize object item.
+               } else {
+                       jQuery.each( obj, function( k, v ) {
+                               buildParams( prefix + "[" + k + "]", v, traditional, add );
+                       });
+               }
+                                       
+       } else {
+               // Serialize scalar item.
+               add( prefix, obj );
+       }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+       etag: {},
+
+       handleError: function( s, xhr, status, e ) {
+               // If a local callback was specified, fire it
+               if ( s.error ) {
+                       s.error.call( s.context, xhr, status, e );
+               }
+
+               // Fire the global callback
+               if ( s.global ) {
+                       jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] );
+               }
+       },
+
+       handleSuccess: function( s, xhr, status, data ) {
+               // If a local callback was specified, fire it and pass it the data
+               if ( s.success ) {
+                       s.success.call( s.context, data, status, xhr );
+               }
+
+               // Fire the global callback
+               if ( s.global ) {
+                       jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] );
+               }
+       },
+
+       handleComplete: function( s, xhr, status ) {
+               // Process result
+               if ( s.complete ) {
+                       s.complete.call( s.context, xhr, status );
+               }
+
+               // The request was completed
+               if ( s.global ) {
+                       jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] );
+               }
+
+               // Handle the global AJAX counter
+               if ( s.global && jQuery.active-- === 1 ) {
+                       jQuery.event.trigger( "ajaxStop" );
+               }
+       },
+               
+       triggerGlobal: function( s, type, args ) {
+               (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args);
+       },
+
+       // Determines if an XMLHttpRequest was successful or not
+       httpSuccess: function( xhr ) {
+               try {
+                       // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
+                       return !xhr.status && location.protocol === "file:" ||
+                               xhr.status >= 200 && xhr.status < 300 ||
+                               xhr.status === 304 || xhr.status === 1223;
+               } catch(e) {}
+
+               return false;
+       },
+
+       // Determines if an XMLHttpRequest returns NotModified
+       httpNotModified: function( xhr, url ) {
+               var lastModified = xhr.getResponseHeader("Last-Modified"),
+                       etag = xhr.getResponseHeader("Etag");
+
+               if ( lastModified ) {
+                       jQuery.lastModified[url] = lastModified;
+               }
+
+               if ( etag ) {
+                       jQuery.etag[url] = etag;
+               }
+
+               return xhr.status === 304;
+       },
+
+       httpData: function( xhr, type, s ) {
+               var ct = xhr.getResponseHeader("content-type") || "",
+                       xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
+                       data = xml ? xhr.responseXML : xhr.responseText;
+
+               if ( xml && data.documentElement.nodeName === "parsererror" ) {
+                       jQuery.error( "parsererror" );
+               }
+
+               // Allow a pre-filtering function to sanitize the response
+               // s is checked to keep backwards compatibility
+               if ( s && s.dataFilter ) {
+                       data = s.dataFilter( data, type );
+               }
+
+               // The filter can actually parse the response
+               if ( typeof data === "string" ) {
+                       // Get the JavaScript object, if JSON is used.
+                       if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
+                               data = jQuery.parseJSON( data );
+
+                       // If the type is "script", eval it in global context
+                       } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
+                               jQuery.globalEval( data );
+                       }
+               }
+
+               return data;
+       }
+
+});
+
+/*
+ * Create the request object; Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+if ( window.ActiveXObject ) {
+       jQuery.ajaxSettings.xhr = function() {
+               if ( window.location.protocol !== "file:" ) {
+                       try {
+                               return new window.XMLHttpRequest();
+                       } catch(xhrError) {}
+               }
+
+               try {
+                       return new window.ActiveXObject("Microsoft.XMLHTTP");
+               } catch(activeError) {}
+       };
+}
+
+// Does this browser support XHR requests?
+jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();
+
+
+
+
+var elemdisplay = {},
+       rfxtypes = /^(?:toggle|show|hide)$/,
+       rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/,
+       timerId,
+       fxAttrs = [
+               // height animations
+               [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+               // width animations
+               [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+               // opacity animations
+               [ "opacity" ]
+       ];
+
+jQuery.fn.extend({
+       show: function( speed, easing, callback ) {
+               var elem, display;
+
+               if ( speed || speed === 0 ) {
+                       return this.animate( genFx("show", 3), speed, easing, callback);
+
+               } else {
+                       for ( var i = 0, j = this.length; i < j; i++ ) {
+                               elem = this[i];
+                               display = elem.style.display;
+
+                               // Reset the inline display of this element to learn if it is
+                               // being hidden by cascaded rules or not
+                               if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
+                                       display = elem.style.display = "";
+                               }
+
+                               // Set elements which have been overridden with display: none
+                               // in a stylesheet to whatever the default browser style is
+                               // for such an element
+                               if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
+                                       jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
+                               }
+                       }
+
+                       // Set the display of most of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( i = 0; i < j; i++ ) {
+                               elem = this[i];
+                               display = elem.style.display;
+
+                               if ( display === "" || display === "none" ) {
+                                       elem.style.display = jQuery.data(elem, "olddisplay") || "";
+                               }
+                       }
+
+                       return this;
+               }
+       },
+
+       hide: function( speed, easing, callback ) {
+               if ( speed || speed === 0 ) {
+                       return this.animate( genFx("hide", 3), speed, easing, callback);
+
+               } else {
+                       for ( var i = 0, j = this.length; i < j; i++ ) {
+                               var display = jQuery.css( this[i], "display" );
+
+                               if ( display !== "none" ) {
+                                       jQuery.data( this[i], "olddisplay", display );
+                               }
+                       }
+
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( i = 0; i < j; i++ ) {
+                               this[i].style.display = "none";
+                       }
+
+                       return this;
+               }
+       },
+
+       // Save the old toggle function
+       _toggle: jQuery.fn.toggle,
+
+       toggle: function( fn, fn2, callback ) {
+               var bool = typeof fn === "boolean";
+
+               if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+                       this._toggle.apply( this, arguments );
+
+               } else if ( fn == null || bool ) {
+                       this.each(function() {
+                               var state = bool ? fn : jQuery(this).is(":hidden");
+                               jQuery(this)[ state ? "show" : "hide" ]();
+                       });
+
+               } else {
+                       this.animate(genFx("toggle", 3), fn, fn2, callback);
+               }
+
+               return this;
+       },
+
+       fadeTo: function( speed, to, easing, callback ) {
+               return this.filter(":hidden").css("opacity", 0).show().end()
+                                       .animate({opacity: to}, speed, easing, callback);
+       },
+
+       animate: function( prop, speed, easing, callback ) {
+               var optall = jQuery.speed(speed, easing, callback);
+
+               if ( jQuery.isEmptyObject( prop ) ) {
+                       return this.each( optall.complete );
+               }
+
+               return this[ optall.queue === false ? "each" : "queue" ](function() {
+                       // XXX 'this' does not always have a nodeName when running the
+                       // test suite
+
+                       var opt = jQuery.extend({}, optall), p,
+                               isElement = this.nodeType === 1,
+                               hidden = isElement && jQuery(this).is(":hidden"),
+                               self = this;
+
+                       for ( p in prop ) {
+                               var name = jQuery.camelCase( p );
+
+                               if ( p !== name ) {
+                                       prop[ name ] = prop[ p ];
+                                       delete prop[ p ];
+                                       p = name;
+                               }
+
+                               if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
+                                       return opt.complete.call(this);
+                               }
+
+                               if ( isElement && ( p === "height" || p === "width" ) ) {
+                                       // Make sure that nothing sneaks out
+                                       // Record all 3 overflow attributes because IE does not
+                                       // change the overflow attribute when overflowX and
+                                       // overflowY are set to the same value
+                                       opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+                                       // Set display property to inline-block for height/width
+                                       // animations on inline elements that are having width/height
+                                       // animated
+                                       if ( jQuery.css( this, "display" ) === "inline" &&
+                                                       jQuery.css( this, "float" ) === "none" ) {
+                                               if ( !jQuery.support.inlineBlockNeedsLayout ) {
+                                                       this.style.display = "inline-block";
+
+                                               } else {
+                                                       var display = defaultDisplay(this.nodeName);
+
+                                                       // inline-level elements accept inline-block;
+                                                       // block-level elements need to be inline with layout
+                                                       if ( display === "inline" ) {
+                                                               this.style.display = "inline-block";
+
+                                                       } else {
+                                                               this.style.display = "inline";
+                                                               this.style.zoom = 1;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if ( jQuery.isArray( prop[p] ) ) {
+                                       // Create (if needed) and add to specialEasing
+                                       (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+                                       prop[p] = prop[p][0];
+                               }
+                       }
+
+                       if ( opt.overflow != null ) {
+                               this.style.overflow = "hidden";
+                       }
+
+                       opt.curAnim = jQuery.extend({}, prop);
+
+                       jQuery.each( prop, function( name, val ) {
+                               var e = new jQuery.fx( self, opt, name );
+
+                               if ( rfxtypes.test(val) ) {
+                                       e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+
+                               } else {
+                                       var parts = rfxnum.exec(val),
+                                               start = e.cur() || 0;
+
+                                       if ( parts ) {
+                                               var end = parseFloat( parts[2] ),
+                                                       unit = parts[3] || "px";
+
+                                               // We need to compute starting value
+                                               if ( unit !== "px" ) {
+                                                       jQuery.style( self, name, (end || 1) + unit);
+                                                       start = ((end || 1) / e.cur()) * start;
+                                                       jQuery.style( self, name, start + unit);
+                                               }
+
+                                               // If a +=/-= token was provided, we're doing a relative animation
+                                               if ( parts[1] ) {
+                                                       end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+                                               }
+
+                                               e.custom( start, end, unit );
+
+                                       } else {
+                                               e.custom( start, val, "" );
+                                       }
+                               }
+                       });
+
+                       // For JS strict compliance
+                       return true;
+               });
+       },
+
+       stop: function( clearQueue, gotoEnd ) {
+               var timers = jQuery.timers;
+
+               if ( clearQueue ) {
+                       this.queue([]);
+               }
+
+               this.each(function() {
+                       // go in reverse order so anything added to the queue during the loop is ignored
+                       for ( var i = timers.length - 1; i >= 0; i-- ) {
+                               if ( timers[i].elem === this ) {
+                                       if (gotoEnd) {
+                                               // force the next step to be the last
+                                               timers[i](true);
+                                       }
+
+                                       timers.splice(i, 1);
+                               }
+                       }
+               });
+
+               // start the next in the queue if the last step wasn't forced
+               if ( !gotoEnd ) {
+                       this.dequeue();
+               }
+
+               return this;
+       }
+
+});
+
+function genFx( type, num ) {
+       var obj = {};
+
+       jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+               obj[ this ] = type;
+       });
+
+       return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx("show", 1),
+       slideUp: genFx("hide", 1),
+       slideToggle: genFx("toggle", 1),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" },
+       fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return this.animate( props, speed, easing, callback );
+       };
+});
+
+jQuery.extend({
+       speed: function( speed, easing, fn ) {
+               var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
+                       complete: fn || !fn && easing ||
+                               jQuery.isFunction( speed ) && speed,
+                       duration: speed,
+                       easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
+               };
+
+               opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+                       opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
+
+               // Queueing
+               opt.old = opt.complete;
+               opt.complete = function() {
+                       if ( opt.queue !== false ) {
+                               jQuery(this).dequeue();
+                       }
+                       if ( jQuery.isFunction( opt.old ) ) {
+                               opt.old.call( this );
+                       }
+               };
+
+               return opt;
+       },
+
+       easing: {
+               linear: function( p, n, firstNum, diff ) {
+                       return firstNum + diff * p;
+               },
+               swing: function( p, n, firstNum, diff ) {
+                       return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
+               }
+       },
+
+       timers: [],
+
+       fx: function( elem, options, prop ) {
+               this.options = options;
+               this.elem = elem;
+               this.prop = prop;
+
+               if ( !options.orig ) {
+                       options.orig = {};
+               }
+       }
+
+});
+
+jQuery.fx.prototype = {
+       // Simple function for setting a style value
+       update: function() {
+               if ( this.options.step ) {
+                       this.options.step.call( this.elem, this.now, this );
+               }
+
+               (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
+       },
+
+       // Get the current size
+       cur: function() {
+               if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
+                       return this.elem[ this.prop ];
+               }
+
+               var r = parseFloat( jQuery.css( this.elem, this.prop ) );
+               return r && r > -10000 ? r : 0;
+       },
+
+       // Start an animation from one number to another
+       custom: function( from, to, unit ) {
+               var self = this,
+                       fx = jQuery.fx;
+
+               this.startTime = jQuery.now();
+               this.start = from;
+               this.end = to;
+               this.unit = unit || this.unit || "px";
+               this.now = this.start;
+               this.pos = this.state = 0;
+
+               function t( gotoEnd ) {
+                       return self.step(gotoEnd);
+               }
+
+               t.elem = this.elem;
+
+               if ( t() && jQuery.timers.push(t) && !timerId ) {
+                       timerId = setInterval(fx.tick, fx.interval);
+               }
+       },
+
+       // Simple 'show' function
+       show: function() {
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+               this.options.show = true;
+
+               // Begin the animation
+               // Make sure that we start at a small width/height to avoid any
+               // flash of content
+               this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
+
+               // Start by showing the element
+               jQuery( this.elem ).show();
+       },
+
+       // Simple 'hide' function
+       hide: function() {
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
+               this.options.hide = true;
+
+               // Begin the animation
+               this.custom(this.cur(), 0);
+       },
+
+       // Each step of an animation
+       step: function( gotoEnd ) {
+               var t = jQuery.now(), done = true;
+
+               if ( gotoEnd || t >= this.options.duration + this.startTime ) {
+                       this.now = this.end;
+                       this.pos = this.state = 1;
+                       this.update();
+
+                       this.options.curAnim[ this.prop ] = true;
+
+                       for ( var i in this.options.curAnim ) {
+                               if ( this.options.curAnim[i] !== true ) {
+                                       done = false;
+                               }
+                       }
+
+                       if ( done ) {
+                               // Reset the overflow
+                               if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+                                       var elem = this.elem,
+                                               options = this.options;
+
+                                       jQuery.each( [ "", "X", "Y" ], function (index, value) {
+                                               elem.style[ "overflow" + value ] = options.overflow[index];
+                                       } );
+                               }
+
+                               // Hide the element if the "hide" operation was done
+                               if ( this.options.hide ) {
+                                       jQuery(this.elem).hide();
+                               }
+
+                               // Reset the properties, if the item has been hidden or shown
+                               if ( this.options.hide || this.options.show ) {
+                                       for ( var p in this.options.curAnim ) {
+                                               jQuery.style( this.elem, p, this.options.orig[p] );
+                                       }
+                               }
+
+                               // Execute the complete function
+                               this.options.complete.call( this.elem );
+                       }
+
+                       return false;
+
+               } else {
+                       var n = t - this.startTime;
+                       this.state = n / this.options.duration;
+
+                       // Perform the easing function, defaults to swing
+                       var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
+                       var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
+                       this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
+                       this.now = this.start + ((this.end - this.start) * this.pos);
+
+                       // Perform the next step of the animation
+                       this.update();
+               }
+
+               return true;
+       }
+};
+
+jQuery.extend( jQuery.fx, {
+       tick: function() {
+               var timers = jQuery.timers;
+
+               for ( var i = 0; i < timers.length; i++ ) {
+                       if ( !timers[i]() ) {
+                               timers.splice(i--, 1);
+                       }
+               }
+
+               if ( !timers.length ) {
+                       jQuery.fx.stop();
+               }
+       },
+
+       interval: 13,
+
+       stop: function() {
+               clearInterval( timerId );
+               timerId = null;
+       },
+
+       speeds: {
+               slow: 600,
+               fast: 200,
+               // Default speed
+               _default: 400
+       },
+
+       step: {
+               opacity: function( fx ) {
+                       jQuery.style( fx.elem, "opacity", fx.now );
+               },
+
+               _default: function( fx ) {
+                       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+                               fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+                       } else {
+                               fx.elem[ fx.prop ] = fx.now;
+                       }
+               }
+       }
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.animated = function( elem ) {
+               return jQuery.grep(jQuery.timers, function( fn ) {
+                       return elem === fn.elem;
+               }).length;
+       };
+}
+
+function defaultDisplay( nodeName ) {
+       if ( !elemdisplay[ nodeName ] ) {
+               var elem = jQuery("<" + nodeName + ">").appendTo("body"),
+                       display = elem.css("display");
+
+               elem.remove();
+
+               if ( display === "none" || display === "" ) {
+                       display = "block";
+               }
+
+               elemdisplay[ nodeName ] = display;
+       }
+
+       return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+       rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+       jQuery.fn.offset = function( options ) {
+               var elem = this[0], box;
+
+               if ( options ) { 
+                       return this.each(function( i ) {
+                               jQuery.offset.setOffset( this, options, i );
+                       });
+               }
+
+               if ( !elem || !elem.ownerDocument ) {
+                       return null;
+               }
+
+               if ( elem === elem.ownerDocument.body ) {
+                       return jQuery.offset.bodyOffset( elem );
+               }
+
+               try {
+                       box = elem.getBoundingClientRect();
+               } catch(e) {}
+
+               var doc = elem.ownerDocument,
+                       docElem = doc.documentElement;
+
+               // Make sure we're not dealing with a disconnected DOM node
+               if ( !box || !jQuery.contains( docElem, elem ) ) {
+                       return box || { top: 0, left: 0 };
+               }
+
+               var body = doc.body,
+                       win = getWindow(doc),
+                       clientTop  = docElem.clientTop  || body.clientTop  || 0,
+                       clientLeft = docElem.clientLeft || body.clientLeft || 0,
+                       scrollTop  = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ),
+                       scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
+                       top  = box.top  + scrollTop  - clientTop,
+                       left = box.left + scrollLeft - clientLeft;
+
+               return { top: top, left: left };
+       };
+
+} else {
+       jQuery.fn.offset = function( options ) {
+               var elem = this[0];
+
+               if ( options ) { 
+                       return this.each(function( i ) {
+                               jQuery.offset.setOffset( this, options, i );
+                       });
+               }
+
+               if ( !elem || !elem.ownerDocument ) {
+                       return null;
+               }
+
+               if ( elem === elem.ownerDocument.body ) {
+                       return jQuery.offset.bodyOffset( elem );
+               }
+
+               jQuery.offset.initialize();
+
+               var computedStyle,
+                       offsetParent = elem.offsetParent,
+                       prevOffsetParent = elem,
+                       doc = elem.ownerDocument,
+                       docElem = doc.documentElement,
+                       body = doc.body,
+                       defaultView = doc.defaultView,
+                       prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+                       top = elem.offsetTop,
+                       left = elem.offsetLeft;
+
+               while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+                       if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+                               break;
+                       }
+
+                       computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+                       top  -= elem.scrollTop;
+                       left -= elem.scrollLeft;
+
+                       if ( elem === offsetParent ) {
+                               top  += elem.offsetTop;
+                               left += elem.offsetLeft;
+
+                               if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+                                       top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+                                       left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+                               }
+
+                               prevOffsetParent = offsetParent;
+                               offsetParent = elem.offsetParent;
+                       }
+
+                       if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+                               top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+                               left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+                       }
+
+                       prevComputedStyle = computedStyle;
+               }
+
+               if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+                       top  += body.offsetTop;
+                       left += body.offsetLeft;
+               }
+
+               if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+                       top  += Math.max( docElem.scrollTop, body.scrollTop );
+                       left += Math.max( docElem.scrollLeft, body.scrollLeft );
+               }
+
+               return { top: top, left: left };
+       };
+}
+
+jQuery.offset = {
+       initialize: function() {
+               var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
+                       html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+
+               jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
+
+               container.innerHTML = html;
+               body.insertBefore( container, body.firstChild );
+               innerDiv = container.firstChild;
+               checkDiv = innerDiv.firstChild;
+               td = innerDiv.nextSibling.firstChild.firstChild;
+
+               this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
+               this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
+
+               checkDiv.style.position = "fixed";
+               checkDiv.style.top = "20px";
+
+               // safari subtracts parent border width here which is 5px
+               this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+               checkDiv.style.position = checkDiv.style.top = "";
+
+               innerDiv.style.overflow = "hidden";
+               innerDiv.style.position = "relative";
+
+               this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
+
+               this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
+
+               body.removeChild( container );
+               body = container = innerDiv = checkDiv = table = td = null;
+               jQuery.offset.initialize = jQuery.noop;
+       },
+
+       bodyOffset: function( body ) {
+               var top = body.offsetTop,
+                       left = body.offsetLeft;
+
+               jQuery.offset.initialize();
+
+               if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+               }
+
+               return { top: top, left: left };
+       },
+       
+       setOffset: function( elem, options, i ) {
+               var position = jQuery.css( elem, "position" );
+
+               // set position first, in-case top/left are set even on static elem
+               if ( position === "static" ) {
+                       elem.style.position = "relative";
+               }
+
+               var curElem = jQuery( elem ),
+                       curOffset = curElem.offset(),
+                       curCSSTop = jQuery.css( elem, "top" ),
+                       curCSSLeft = jQuery.css( elem, "left" ),
+                       calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
+                       props = {}, curPosition = {}, curTop, curLeft;
+
+               // need to be able to calculate position if either top or left is auto and position is absolute
+               if ( calculatePosition ) {
+                       curPosition = curElem.position();
+               }
+
+               curTop  = calculatePosition ? curPosition.top  : parseInt( curCSSTop,  10 ) || 0;
+               curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;
+
+               if ( jQuery.isFunction( options ) ) {
+                       options = options.call( elem, i, curOffset );
+               }
+
+               if (options.top != null) {
+                       props.top = (options.top - curOffset.top) + curTop;
+               }
+               if (options.left != null) {
+                       props.left = (options.left - curOffset.left) + curLeft;
+               }
+               
+               if ( "using" in options ) {
+                       options.using.call( elem, props );
+               } else {
+                       curElem.css( props );
+               }
+       }
+};
+
+
+jQuery.fn.extend({
+       position: function() {
+               if ( !this[0] ) {
+                       return null;
+               }
+
+               var elem = this[0],
+
+               // Get *real* offsetParent
+               offsetParent = this.offsetParent(),
+
+               // Get correct offsets
+               offset       = this.offset(),
+               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+               // Subtract element margins
+               // note: when an element has margin: auto the offsetLeft and marginLeft
+               // are the same in Safari causing offset.left to incorrectly be 0
+               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+               // Add offsetParent borders
+               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+               // Subtract the two offsets
+               return {
+                       top:  offset.top  - parentOffset.top,
+                       left: offset.left - parentOffset.left
+               };
+       },
+
+       offsetParent: function() {
+               return this.map(function() {
+                       var offsetParent = this.offsetParent || document.body;
+                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+                               offsetParent = offsetParent.offsetParent;
+                       }
+                       return offsetParent;
+               });
+       }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+       var method = "scroll" + name;
+
+       jQuery.fn[ method ] = function(val) {
+               var elem = this[0], win;
+               
+               if ( !elem ) {
+                       return null;
+               }
+
+               if ( val !== undefined ) {
+                       // Set the scroll offset
+                       return this.each(function() {
+                               win = getWindow( this );
+
+                               if ( win ) {
+                                       win.scrollTo(
+                                               !i ? val : jQuery(win).scrollLeft(),
+                                                i ? val : jQuery(win).scrollTop()
+                                       );
+
+                               } else {
+                                       this[ method ] = val;
+                               }
+                       });
+               } else {
+                       win = getWindow( elem );
+
+                       // Return the scroll offset
+                       return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+                               jQuery.support.boxModel && win.document.documentElement[ method ] ||
+                                       win.document.body[ method ] :
+                               elem[ method ];
+               }
+       };
+});
+
+function getWindow( elem ) {
+       return jQuery.isWindow( elem ) ?
+               elem :
+               elem.nodeType === 9 ?
+                       elem.defaultView || elem.parentWindow :
+                       false;
+}
+
+
+
+
+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+       var type = name.toLowerCase();
+
+       // innerHeight and innerWidth
+       jQuery.fn["inner" + name] = function() {
+               return this[0] ?
+                       parseFloat( jQuery.css( this[0], type, "padding" ) ) :
+                       null;
+       };
+
+       // outerHeight and outerWidth
+       jQuery.fn["outer" + name] = function( margin ) {
+               return this[0] ?
+                       parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
+                       null;
+       };
+
+       jQuery.fn[ type ] = function( size ) {
+               // Get window width or height
+               var elem = this[0];
+               if ( !elem ) {
+                       return size == null ? null : this;
+               }
+               
+               if ( jQuery.isFunction( size ) ) {
+                       return this.each(function( i ) {
+                               var self = jQuery( this );
+                               self[ type ]( size.call( this, i, self[ type ]() ) );
+                       });
+               }
+
+               if ( jQuery.isWindow( elem ) ) {
+                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+                       return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
+                               elem.document.body[ "client" + name ];
+
+               // Get document width or height
+               } else if ( elem.nodeType === 9 ) {
+                       // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+                       return Math.max(
+                               elem.documentElement["client" + name],
+                               elem.body["scroll" + name], elem.documentElement["scroll" + name],
+                               elem.body["offset" + name], elem.documentElement["offset" + name]
+                       );
+
+               // Get or set width or height on the element
+               } else if ( size === undefined ) {
+                       var orig = jQuery.css( elem, type ),
+                               ret = parseFloat( orig );
+
+                       return jQuery.isNaN( ret ) ? orig : ret;
+
+               // Set the width or height on the element (default to pixels if value is unitless)
+               } else {
+                       return this.css( type, typeof size === "string" ? size : size + "px" );
+               }
+       };
+
+});
+
+
+})(window);
diff --git a/jappixmini/jappix/js/jquery.placeholder.js b/jappixmini/jappix/js/jquery.placeholder.js
new file mode 100644 (file)
index 0000000..834bda6
--- /dev/null
@@ -0,0 +1,116 @@
+(function($) {
+       $.extend({
+               placeholder : {
+                       settings : {
+                               focusClass: 'placeholderFocus',
+                               activeClass: 'placeholder',
+                               overrideSupport: false,
+                               preventRefreshIssues: true
+                       },
+                       debug : false,
+                       log : function(msg){
+                               if(!$.placeholder.debug) return;
+                               msg = "[Placeholder] " + msg;
+                               $.placeholder.hasFirebug ?
+                               console.log(msg) :
+                               $.placeholder.hasConsoleLog ?
+                                       window.console.log(msg) :
+                                       alert(msg);
+                       },
+                       hasFirebug : "console" in window && "firebug" in window.console,
+                       hasConsoleLog: "console" in window && "log" in window.console
+               }
+
+       });
+
+    // check browser support for placeholder
+    $.support.placeholder = 'placeholder' in document.createElement('input');
+
+       // Replace the val function to never return placeholders
+       $.fn.plVal = $.fn.val;
+       $.fn.val = function(value) {
+               $.placeholder.log('in val');
+               if(this[0]) {
+                       $.placeholder.log('have found an element');
+                       var el = $(this[0]);
+                       if(value != undefined)
+                       {
+                               $.placeholder.log('in setter');
+                               var currentValue = el.plVal();
+                               var returnValue = $(this).plVal(value);
+                               if(el.hasClass($.placeholder.settings.activeClass) && currentValue == el.attr('placeholder')){
+                                       el.removeClass($.placeholder.settings.activeClass);
+                               }
+                               return returnValue;
+                       }
+
+                       if(el.hasClass($.placeholder.settings.activeClass) && el.plVal() == el.attr('placeholder')) {
+                               $.placeholder.log('returning empty because its a placeholder');
+                               return '';
+                       } else {
+                               $.placeholder.log('returning original val');
+                               return el.plVal();
+                       }
+               }
+               $.placeholder.log('returning undefined');
+               return undefined;
+       };
+
+       // Clear placeholder values upon page reload
+       $(window).bind('beforeunload.placeholder', function() {
+               var els = $('input.placeholderActive' );
+               if(els.length > 0)
+                       els.val('').attr('autocomplete','off');
+       });
+
+
+    // plugin code
+       $.fn.placeholder = function(opts) {
+               opts = $.extend({},$.placeholder.settings, opts);
+
+               // we don't have to do anything if the browser supports placeholder
+               if(!opts.overrideSupport && $.support.placeholder)
+                   return this;
+                       
+        return this.each(function() {
+            var $el = $(this);
+
+            // skip if we do not have the placeholder attribute
+            if(!$el.is('[placeholder]'))
+                return;
+
+            // we cannot do password fields, but supported browsers can
+            if($el.is(':password'))
+                return;
+                       
+                       // Prevent values from being reapplied on refresh
+                       if(opts.preventRefreshIssues)
+                               $el.attr('autocomplete','off');
+
+            $el.bind('focus.placeholder', function(){
+                var $el = $(this);
+                if(this.value == $el.attr('placeholder') && $el.hasClass(opts.activeClass))
+                    $el.val('')
+                       .removeClass(opts.activeClass)
+                       .addClass(opts.focusClass);
+            });
+            $el.bind('blur.placeholder', function(){
+                var $el = $(this);
+                               
+                               $el.removeClass(opts.focusClass);
+
+                if(this.value == '')
+                  $el.val($el.attr('placeholder'))
+                     .addClass(opts.activeClass);
+            });
+
+            $el.triggerHandler('blur');
+                       
+                       // Prevent incorrect form values being posted
+                       $el.parents('form').submit(function(){
+                               $el.triggerHandler('focus.placeholder');
+                       });
+
+        });
+    };
+})(jQuery);
diff --git a/jappixmini/jappix/js/jquery.textrange.js b/jappixmini/jappix/js/jquery.textrange.js
new file mode 100644 (file)
index 0000000..20bd028
--- /dev/null
@@ -0,0 +1,14 @@
+$.fn.selectRange = function(start, end) {
+    return this.each(function() {
+        if (this.setSelectionRange) {
+            this.focus();
+            this.setSelectionRange(start, end);
+        } else if (this.createTextRange) {
+            var range = this.createTextRange();
+            range.collapse(true);
+            range.moveEnd('character', end);
+            range.moveStart('character', start);
+            range.select();
+        }
+    });
+};
diff --git a/jappixmini/jappix/js/jquery.timers.js b/jappixmini/jappix/js/jquery.timers.js
new file mode 100644 (file)
index 0000000..ae3d6ac
--- /dev/null
@@ -0,0 +1,138 @@
+/**\r
+ * jQuery.timers - Timer abstractions for jQuery\r
+ * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)\r
+ * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).\r
+ * Date: 2009/10/16\r
+ *\r
+ * @author Blair Mitchelmore\r
+ * @version 1.2\r
+ *\r
+ **/\r
+\r
+jQuery.fn.extend({\r
+       everyTime: function(interval, label, fn, times) {\r
+               return this.each(function() {\r
+                       jQuery.timer.add(this, interval, label, fn, times);\r
+               });\r
+       },\r
+       oneTime: function(interval, label, fn) {\r
+               return this.each(function() {\r
+                       jQuery.timer.add(this, interval, label, fn, 1);\r
+               });\r
+       },\r
+       stopTime: function(label, fn) {\r
+               return this.each(function() {\r
+                       jQuery.timer.remove(this, label, fn);\r
+               });\r
+       }\r
+});\r
+\r
+jQuery.extend({\r
+       timer: {\r
+               global: [],\r
+               guid: 1,\r
+               dataKey: "jQuery.timer",\r
+               regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,\r
+               powers: {\r
+                       // Yeah this is major overkill...\r
+                       'ms': 1,\r
+                       'cs': 10,\r
+                       'ds': 100,\r
+                       's': 1000,\r
+                       'das': 10000,\r
+                       'hs': 100000,\r
+                       'ks': 1000000\r
+               },\r
+               timeParse: function(value) {\r
+                       if (value == undefined || value == null)\r
+                               return null;\r
+                       var result = this.regex.exec(jQuery.trim(value.toString()));\r
+                       if (result[2]) {\r
+                               var num = parseFloat(result[1]);\r
+                               var mult = this.powers[result[2]] || 1;\r
+                               return num * mult;\r
+                       } else {\r
+                               return value;\r
+                       }\r
+               },\r
+               add: function(element, interval, label, fn, times) {\r
+                       var counter = 0;\r
+\r
+                       if (jQuery.isFunction(label)) {\r
+                               if (!times)\r
+                                       times = fn;\r
+                               fn = label;\r
+                               label = interval;\r
+                       }\r
+\r
+                       interval = jQuery.timer.timeParse(interval);\r
+\r
+                       if (typeof interval != 'number' || isNaN(interval) || interval < 0)\r
+                               return;\r
+\r
+                       if (typeof times != 'number' || isNaN(times) || times < 0)\r
+                               times = 0;\r
+\r
+                       times = times || 0;\r
+\r
+                       var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});\r
+\r
+                       if (!timers[label])\r
+                               timers[label] = {};\r
+\r
+                       fn.timerID = fn.timerID || this.guid++;\r
+\r
+                       var handler = function() {\r
+                               if ((++counter > times && times !== 0) || fn.call(element, counter) === false)\r
+                                       jQuery.timer.remove(element, label, fn);\r
+                       };\r
+\r
+                       handler.timerID = fn.timerID;\r
+\r
+                       if (!timers[label][fn.timerID])\r
+                               timers[label][fn.timerID] = window.setInterval(handler,interval);\r
+\r
+                       this.global.push( element );\r
+\r
+               },\r
+               remove: function(element, label, fn) {\r
+                       var timers = jQuery.data(element, this.dataKey), ret;\r
+\r
+                       if ( timers ) {\r
+\r
+                               if (!label) {\r
+                                       for ( label in timers )\r
+                                               this.remove(element, label, fn);\r
+                               } else if ( timers[label] ) {\r
+                                       if ( fn ) {\r
+                                               if ( fn.timerID ) {\r
+                                                       window.clearInterval(timers[label][fn.timerID]);\r
+                                                       delete timers[label][fn.timerID];\r
+                                               }\r
+                                       } else {\r
+                                               for ( var fn in timers[label] ) {\r
+                                                       window.clearInterval(timers[label][fn]);\r
+                                                       delete timers[label][fn];\r
+                                               }\r
+                                       }\r
+\r
+                                       for ( ret in timers[label] ) break;\r
+                                       if ( !ret ) {\r
+                                               ret = null;\r
+                                               delete timers[label];\r
+                                       }\r
+                               }\r
+\r
+                               for ( ret in timers ) break;\r
+                               if ( !ret )\r
+                                       jQuery.removeData(element, this.dataKey);\r
+                       }\r
+               }\r
+       }\r
+});\r
+\r
+jQuery(window).bind("unload", function() {\r
+       jQuery.each(jQuery.timer.global, function(index, item) {\r
+               jQuery.timer.remove(item);\r
+       });\r
+});\r
diff --git a/jappixmini/jappix/js/jsjac.js b/jappixmini/jappix/js/jsjac.js
new file mode 100644 (file)
index 0000000..752747d
--- /dev/null
@@ -0,0 +1,4288 @@
+/*
+
+Jappix - An open social platform
+This is the JSJaC library for Jappix (from trunk)
+
+-------------------------------------------------
+
+Licenses: Mozilla Public License version 1.1, GNU GPL, AGPL
+Authors: Stefan Strigler, Vanaryon, Zash
+Last revision: 25/08/11
+
+*/
+
+/**
+ * @fileoverview Magic dependency loading. Taken from script.aculo.us
+ * and modified to break it.
+ * @author Stefan Strigler steve@zeank.in-berlin.de 
+ * @version $Revision$
+ */
+
+var JSJaC = {
+  Version: '$Rev$',
+  bind: function(fn, obj, optArg) {
+    return function(arg) {
+      return fn.apply(obj, [arg, optArg]);
+    };
+  }
+};
+
+if (typeof JSJaCConnection == 'undefined')
+  JSJaC.load();
+
+
+
+/* Copyright 2006 Erik Arvidsson
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you
+ * may not use this file except in compliance with the License.  You
+ * may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/**
+ * @fileoverview Wrapper to make working with XmlHttpRequest and the
+ * DOM more convenient (cross browser compliance).
+ * this code is taken from
+ * http://webfx.eae.net/dhtml/xmlextras/xmlextras.html
+ * @author Stefan Strigler steve@zeank.in-berlin.de
+ * @version $Revision$
+ */
+
+/**
+ * XmlHttp factory
+ * @private
+ */
+function XmlHttp() {}
+
+/**
+ * creates a cross browser compliant XmlHttpRequest object
+ */
+XmlHttp.create = function () {
+  try {
+    // Are we cross-domain?
+    if(((BOSH_PROXY == 'on') || (HOST_BOSH_MINI)) && (typeof jXHR == "function")) {
+        // Able to use CORS?
+        if (window.XMLHttpRequest) {
+          var req = new XMLHttpRequest();
+          
+          if (req.withCredentials !== undefined)
+            return req;
+        }
+        
+       return new jXHR();
+    }
+    // Might be local-domain?
+    if (window.XMLHttpRequest) {
+      var req = new XMLHttpRequest();
+      
+      // some versions of Moz do not support the readyState property
+      // and the onreadystate event so we patch it!
+      if (req.readyState == null) {
+       req.readyState = 1;
+       req.addEventListener("load", function () {
+                              req.readyState = 4;
+                              if (typeof req.onreadystatechange == "function")
+                                req.onreadystatechange();
+                            }, false);
+      }
+      
+      return req;
+    }
+    if (window.ActiveXObject) {
+      return new ActiveXObject(XmlHttp.getPrefix() + ".XmlHttp");
+    }
+  }
+  catch (ex) {}
+  // fell through
+  throw new Error("Your browser does not support XmlHttp objects");
+};
+
+/**
+ * used to find the Automation server name
+ * @private
+ */
+XmlHttp.getPrefix = function() {
+  if (XmlHttp.prefix) // I know what you did last summer
+    return XmlHttp.prefix;
+  var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+  var o;
+  for (var i = 0; i < prefixes.length; i++) {
+    try {
+      // try to create the objects
+      o = new ActiveXObject(prefixes[i] + ".XmlHttp");
+      return XmlHttp.prefix = prefixes[i];
+    }
+    catch (ex) {};
+  }
+  throw new Error("Could not find an installed XML parser");
+};
+
+
+/**
+ * XmlDocument factory
+ * @private
+ */
+function XmlDocument() {}
+
+XmlDocument.create = function (name,ns) {
+  name = name || 'foo';
+  ns = ns || '';
+
+  try {
+    var doc;
+    // DOM2
+    if (document.implementation && document.implementation.createDocument) {
+      doc = document.implementation.createDocument(ns, name, null);
+      // some versions of Moz do not support the readyState property
+      // and the onreadystate event so we patch it!
+      if (doc.readyState == null) {
+       doc.readyState = 1;
+       doc.addEventListener("load", function () {
+                              doc.readyState = 4;
+                              if (typeof doc.onreadystatechange == "function")
+                                doc.onreadystatechange();
+                            }, false);
+      }
+    } else if (window.ActiveXObject) {
+      doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument");
+    }
+   
+    if (!doc.documentElement || doc.documentElement.tagName != name ||
+        (doc.documentElement.namespaceURI &&
+         doc.documentElement.namespaceURI != ns)) {
+          try {
+            if (ns != '')
+              doc.appendChild(doc.createElement(name)).
+                setAttribute('xmlns',ns);
+            else
+              doc.appendChild(doc.createElement(name));
+          } catch (dex) {
+            doc = document.implementation.createDocument(ns,name,null);
+           
+            if (doc.documentElement == null)
+              doc.appendChild(doc.createElement(name));
+
+             // fix buggy opera 8.5x
+            if (ns != '' &&
+                doc.documentElement.getAttribute('xmlns') != ns) {
+              doc.documentElement.setAttribute('xmlns',ns);
+            }
+          }
+        }
+   
+    return doc;
+  }
+  catch (ex) { }
+  throw new Error("Your browser does not support XmlDocument objects");
+};
+
+/**
+ * used to find the Automation server name
+ * @private
+ */
+XmlDocument.getPrefix = function() {
+  if (XmlDocument.prefix)
+    return XmlDocument.prefix;
+
+  var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+  var o;
+  for (var i = 0; i < prefixes.length; i++) {
+    try {
+      // try to create the objects
+      o = new ActiveXObject(prefixes[i] + ".DomDocument");
+      return XmlDocument.prefix = prefixes[i];
+    }
+    catch (ex) {};
+  }
+  throw new Error("Could not find an installed XML parser");
+};
+
+
+// Create the loadXML method
+if (typeof(Document) != 'undefined' && window.DOMParser) {
+
+  /**
+   * XMLDocument did not extend the Document interface in some
+   * versions of Mozilla.
+   * @private
+   */
+  Document.prototype.loadXML = function (s) {
+       
+    // parse the string to a new doc
+    var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
+       
+    // remove all initial children
+    while (this.hasChildNodes())
+      this.removeChild(this.lastChild);
+               
+    // insert and import nodes
+    for (var i = 0; i < doc2.childNodes.length; i++) {
+      this.appendChild(this.importNode(doc2.childNodes[i], true));
+    }
+  };
+ }
+
+// Create xml getter for Mozilla
+if (window.XMLSerializer &&
+    window.Node && Node.prototype && Node.prototype.__defineGetter__) {
+
+  /**
+   * xml getter
+   *
+   * This serializes the DOM tree to an XML String
+   *
+   * Usage: var sXml = oNode.xml
+   * @deprecated
+   * @private
+   */
+  // XMLDocument did not extend the Document interface in some versions
+  // of Mozilla. Extend both!
+  XMLDocument.prototype.__defineGetter__("xml", function () {
+                                           return (new XMLSerializer()).serializeToString(this);
+                                         });
+  /**
+   * xml getter
+   *
+   * This serializes the DOM tree to an XML String
+   *
+   * Usage: var sXml = oNode.xml
+   * @deprecated
+   * @private
+   */
+  Document.prototype.__defineGetter__("xml", function () {
+                                        return (new XMLSerializer()).serializeToString(this);
+                                      });
+
+  /**
+   * xml getter
+   *
+   * This serializes the DOM tree to an XML String
+   *
+   * Usage: var sXml = oNode.xml
+   * @deprecated
+   * @private
+   */
+  Node.prototype.__defineGetter__("xml", function () {
+                                    return (new XMLSerializer()).serializeToString(this);
+                                  });
+ }
+
+
+/**
+ * @fileoverview Collection of functions to make live easier
+ * @author Stefan Strigler
+ * @version $Revision$
+ */
+
+/**
+ * Convert special chars to HTML entities
+ * @addon
+ * @return The string with chars encoded for HTML
+ * @type String
+ */
+String.prototype.htmlEnc = function() {
+  if(!this)
+    return this;
+  
+  var str = this.replace(/&/g,"&amp;");
+  str = str.replace(/</g,"&lt;");
+  str = str.replace(/>/g,"&gt;");
+  str = str.replace(/\"/g,"&quot;");
+  str = str.replace(/\n/g,"<br />");
+  return str;
+};
+
+/**
+ * Convert HTML entities to special chars
+ * @addon
+ * @return The normal string
+ * @type String
+ */
+String.prototype.revertHtmlEnc = function() {
+  if(!this)
+    return this;
+  
+  var str = this.replace(/&amp;/gi,'&');
+  str = str.replace(/&lt;/gi,'<');
+  str = str.replace(/&gt;/gi,'>');
+  str = str.replace(/&quot;/gi,'\"');
+  str = str.replace(/<br( )?(\/)?>/gi,'\n');
+  return str;
+};
+
+/**
+ * Converts from jabber timestamps to JavaScript Date objects
+ * @addon
+ * @param {String} ts A string representing a jabber datetime timestamp as
+ * defined by {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082}
+ * @return A javascript Date object corresponding to the jabber DateTime given
+ * @type Date
+ */
+Date.jab2date = function(ts) {
+  // Get the UTC date
+  var date = new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2)));
+  
+  if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset
+    var date_offset = date.getTimezoneOffset() * 60 * 1000;
+    var offset = new Date();
+    offset.setTime(0);
+    offset.setUTCHours(ts.substr(ts.length-5,2));
+    offset.setUTCMinutes(ts.substr(ts.length-2,2));
+    if (ts.substr(ts.length-6,1) == '+')
+      date.setTime(date.getTime() + offset.getTime() + date_offset);
+    else if (ts.substr(ts.length-6,1) == '-')
+      date.setTime(date.getTime() - offset.getTime() + date_offset);
+  }
+  return date;
+};
+
+/**
+ * Takes a timestamp in the form of 2004-08-13T12:07:04+02:00 as argument
+ * and converts it to some sort of humane readable format
+ * @addon
+ */
+Date.hrTime = function(ts) {
+  return Date.jab2date(ts).toLocaleString();
+};
+
+/**
+ * somewhat opposit to {@link #hrTime}
+ * expects a javascript Date object as parameter and returns a jabber
+ * date string conforming to
+ * {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082}
+ * @see #hrTime
+ * @return The corresponding jabber DateTime string
+ * @type String
+ */
+Date.prototype.jabberDate = function() {
+  var padZero = function(i) {
+    if (i < 10) return "0" + i;
+    return i;
+  };
+
+  var jDate = this.getUTCFullYear() + "-";
+  jDate += padZero(this.getUTCMonth()+1) + "-";
+  jDate += padZero(this.getUTCDate()) + "T";
+  jDate += padZero(this.getUTCHours()) + ":";
+  jDate += padZero(this.getUTCMinutes()) + ":";
+  jDate += padZero(this.getUTCSeconds()) + "Z";
+
+  return jDate;
+};
+
+/**
+ * Determines the maximum of two given numbers
+ * @addon
+ * @param {Number} A a number
+ * @param {Number} B another number
+ * @return the maximum of A and B
+ * @type Number
+ */
+Number.max = function(A, B) {
+  return (A > B)? A : B;
+};
+
+Number.min = function(A, B) {
+  return (A < B)? A : B;
+};
+
+
+/* Copyright (c) 1998 - 2007, Paul Johnston & Contributors
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following
+ * disclaimer. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * @fileoverview Collection of MD5 and SHA1 hashing and encoding
+ * methods.
+ * @author Stefan Strigler steve@zeank.in-berlin.de
+ * @version $Revision$
+ */
+
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = "="; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  x[((len + 64 >> 9) << 4) + 15] = len;
+
+  var w = Array(80);
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+  var e = -1009589776;
+
+  for(var i = 0; i < x.length; i += 16)
+    {
+      var olda = a;
+      var oldb = b;
+      var oldc = c;
+      var oldd = d;
+      var olde = e;
+
+      for(var j = 0; j < 80; j++)
+        {
+          if(j < 16) w[j] = x[i + j];
+          else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+          var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+                           safe_add(safe_add(e, w[j]), sha1_kt(j)));
+          e = d;
+          d = c;
+          c = rol(b, 30);
+          b = a;
+          a = t;
+        }
+
+      a = safe_add(a, olda);
+      b = safe_add(b, oldb);
+      c = safe_add(c, oldc);
+      d = safe_add(d, oldd);
+      e = safe_add(e, olde);
+    }
+  return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+  if(t < 20) return (b & c) | ((~b) & d);
+  if(t < 40) return b ^ c ^ d;
+  if(t < 60) return (b & c) | (b & d) | (c & d);
+  return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
+    (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data
+ */
+function core_hmac_sha1(key, data)
+{
+  var bkey = str2binb(key);
+  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+    {
+      ipad[i] = bkey[i] ^ 0x36363636;
+      opad[i] = bkey[i] ^ 0x5C5C5C5C;
+    }
+
+  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+  return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+    {
+      str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+        hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
+    }
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a base-64 string
+ */
+function binb2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+    {
+      var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
+        | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+        |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
+      for(var j = 0; j < 4; j++)
+        {
+          if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+          else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+        }
+    }
+  return str.replace(/AAA\=(\=*?)$/,'$1'); // cleans garbage chars at end of string
+}
+
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+// var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+// var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+// var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+
+/* #############################################################################
+   UTF-8 Decoder and Encoder
+   base64 Encoder and Decoder
+   written by Tobias Kieslich, justdreams
+   Contact: tobias@justdreams.de                               http://www.justdreams.de/
+   ############################################################################# */
+
+// returns an array of byterepresenting dezimal numbers which represent the
+// plaintext in an UTF-8 encoded version. Expects a string.
+// This function includes an exception management for those nasty browsers like
+// NN401, which returns negative decimal numbers for chars>128. I hate it!!
+// This handling is unfortunately limited to the user's charset. Anyway, it works
+// in most of the cases! Special signs with an unicode>256 return numbers, which
+// can not be converted to the actual unicode and so not to the valid utf-8
+// representation. Anyway, this function does always return values which can not
+// misinterpretd by RC4 or base64 en- or decoding, because every value is >0 and
+// <255!!
+// Arrays are faster and easier to handle in b64 encoding or encrypting....
+function utf8t2d(t)
+{
+  t = t.replace(/\r\n/g,"\n");
+  var d=new Array; var test=String.fromCharCode(237);
+  if (test.charCodeAt(0) < 0)
+    for(var n=0; n<t.length; n++)
+      {
+        var c=t.charCodeAt(n);
+        if (c>0)
+          d[d.length]= c;
+        else {
+          d[d.length]= (((256+c)>>6)|192);
+          d[d.length]= (((256+c)&63)|128);}
+      }
+  else
+    for(var n=0; n<t.length; n++)
+      {
+        var c=t.charCodeAt(n);
+        // all the signs of asci => 1byte
+        if (c<128)
+          d[d.length]= c;
+        // all the signs between 127 and 2047 => 2byte
+        else if((c>127) && (c<2048)) {
+          d[d.length]= ((c>>6)|192);
+          d[d.length]= ((c&63)|128);}
+        // all the signs between 2048 and 66536 => 3byte
+        else {
+          d[d.length]= ((c>>12)|224);
+          d[d.length]= (((c>>6)&63)|128);
+          d[d.length]= ((c&63)|128);}
+      }
+  return d;
+}
+       
+// returns plaintext from an array of bytesrepresenting dezimal numbers, which
+// represent an UTF-8 encoded text; browser which does not understand unicode
+// like NN401 will show "?"-signs instead
+// expects an array of byterepresenting decimals; returns a string
+function utf8d2t(d)
+{
+  var r=new Array; var i=0;
+  while(i<d.length)
+    {
+      if (d[i]<128) {
+        r[r.length]= String.fromCharCode(d[i]); i++;}
+      else if((d[i]>191) && (d[i]<224)) {
+        r[r.length]= String.fromCharCode(((d[i]&31)<<6) | (d[i+1]&63)); i+=2;}
+      else {
+        r[r.length]= String.fromCharCode(((d[i]&15)<<12) | ((d[i+1]&63)<<6) | (d[i+2]&63)); i+=3;}
+    }
+  return r.join("");
+}
+
+// included in <body onload="b64arrays"> it creates two arrays which makes base64
+// en- and decoding faster
+// this speed is noticeable especially when coding larger texts (>5k or so)
+function b64arrays() {
+  var b64s='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+  b64 = new Array();f64 =new Array();
+  for (var i=0; i<b64s.length ;i++) {
+    b64[i] = b64s.charAt(i);
+    f64[b64s.charAt(i)] = i;
+  }
+}
+
+// creates a base64 encoded text out of an array of byerepresenting dezimals
+// it is really base64 :) this makes serversided handling easier
+// expects an array; returns a string
+function b64d2t(d) {
+  var r=new Array; var i=0; var dl=d.length;
+  // this is for the padding
+  if ((dl%3) == 1) {
+    d[d.length] = 0; d[d.length] = 0;}
+  if ((dl%3) == 2)
+    d[d.length] = 0;
+  // from here conversion
+  while (i<d.length)
+    {
+      r[r.length] = b64[d[i]>>2];
+      r[r.length] = b64[((d[i]&3)<<4) | (d[i+1]>>4)];
+      r[r.length] = b64[((d[i+1]&15)<<2) | (d[i+2]>>6)];
+      r[r.length] = b64[d[i+2]&63];
+      i+=3;
+    }
+  // this is again for the padding
+  if ((dl%3) == 1)
+    r[r.length-1] = r[r.length-2] = "=";
+  if ((dl%3) == 2)
+    r[r.length-1] = "=";
+  // we join the array to return a textstring
+  var t=r.join("");
+  return t;
+}
+
+// returns array of byterepresenting numbers created of an base64 encoded text
+// it is still the slowest function in this modul; I hope I can make it faster
+// expects string; returns an array
+function b64t2d(t) {
+  var d=new Array; var i=0;
+  // here we fix this CRLF sequenz created by MS-OS; arrrgh!!!
+  t=t.replace(/\n|\r/g,""); t=t.replace(/=/g,"");
+  while (i<t.length)
+    {
+      d[d.length] = (f64[t.charAt(i)]<<2) | (f64[t.charAt(i+1)]>>4);
+      d[d.length] = (((f64[t.charAt(i+1)]&15)<<4) | (f64[t.charAt(i+2)]>>2));
+      d[d.length] = (((f64[t.charAt(i+2)]&3)<<6) | (f64[t.charAt(i+3)]));
+      i+=4;
+    }
+  if (t.length%4 == 2)
+    d = d.slice(0, d.length-2);
+  if (t.length%4 == 3)
+    d = d.slice(0, d.length-1);
+  return d;
+}
+
+b64arrays();
+
+b64decode = function(s) {
+  return utf8d2t(b64t2d(s));
+}
+
+b64encode = function(s) {
+  return b64d2t(utf8t2d(s));
+}
+
+function cnonce(size) {
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+  var cnonce = '';
+  for (var i=0; i<size; i++) {
+    cnonce += tab.charAt(Math.round(Math.random(new Date().getTime())*(tab.length-1)));
+  }
+  return cnonce;
+}
+
+
+
+JSJAC_HAVEKEYS = true;          // whether to use keys
+JSJAC_NKEYS    = 16;            // number of keys to generate
+JSJAC_INACTIVITY = 300;         // qnd hack to make suspend/resume 
+                                    // work more smoothly with polling
+JSJAC_ERR_COUNT = 10;           // number of retries in case of connection
+                                    // errors
+
+JSJAC_ALLOW_PLAIN = true;       // whether to allow plaintext logins
+
+JSJAC_CHECKQUEUEINTERVAL = 100;   // msecs to poll send queue
+JSJAC_CHECKINQUEUEINTERVAL = 100; // msecs to poll incoming queue
+JSJAC_TIMERVAL = 2000;          // default polling interval
+
+// Options specific to HTTP Binding (BOSH)
+JSJACHBC_MAX_HOLD = 1;          // default for number of connections held by 
+                                    // connection manager 
+JSJACHBC_MAX_WAIT = 20;        // default 'wait' param - how long an idle connection
+                                    // should be held by connection manager
+
+JSJACHBC_BOSH_VERSION  = "1.6";
+JSJACHBC_USE_BOSH_VER  = true;
+
+JSJACHBC_MAXPAUSE = 20;        // how long a suspend/resume cycle may take
+
+/*** END CONFIG ***/
+
+
+/* Copyright (c) 2005-2007 Sam Stephenson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+  json.js
+  taken from prototype.js, made static
+*/
+function JSJaCJSON() {}
+JSJaCJSON.toString = function (obj) {
+  var m = {
+    '\b': '\\b',
+    '\t': '\\t',
+    '\n': '\\n',
+    '\f': '\\f',
+    '\r': '\\r',
+    '"' : '\\"',
+    '\\': '\\\\'
+  },
+  s = {
+    array: function (x) {
+      var a = ['['], b, f, i, l = x.length, v;
+      for (i = 0; i < l; i += 1) {
+        v = x[i];
+        f = s[typeof v];
+        if (f) {
+         try {
+            v = f(v);
+            if (typeof v == 'string') {
+              if (b) {
+                a[a.length] = ',';
+              }
+              a[a.length] = v;
+              b = true;
+            }
+         } catch(e) { 
+         }
+        }
+      }
+      a[a.length] = ']';
+      return a.join('');
+    },
+    'boolean': function (x) {
+      return String(x);
+    },
+    'null': function (x) {
+      return "null";
+    },
+    number: function (x) {
+      return isFinite(x) ? String(x) : 'null';
+    },
+    object: function (x) {
+      if (x) {
+        if (x instanceof Array) {
+          return s.array(x);
+        }
+        var a = ['{'], b, f, i, v;
+        for (i in x) {
+          if (x.hasOwnProperty(i)) {
+            v = x[i];
+            f = s[typeof v];
+            if (f) {
+             try {
+                v = f(v);
+                if (typeof v == 'string') {
+                  if (b) {
+                    a[a.length] = ',';
+                  }
+                  a.push(s.string(i), ':', v);
+                  b = true;
+                }
+             } catch(e) {
+             }
+            }
+          }
+        }
+         
+        a[a.length] = '}';
+        return a.join('');
+      }
+      return 'null';
+    },
+    string: function (x) {
+      if (/["\\\x00-\x1f]/.test(x)) {
+                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+          var c = m[b];
+          if (c) {
+            return c;
+          }
+          c = b.charCodeAt();
+          return '\\u00' +
+          Math.floor(c / 16).toString(16) +
+          (c % 16).toString(16);
+        });
+  }
+  return '"' + x + '"';
+}
+  };
+
+switch (typeof(obj)) {
+ case 'object':
+   return s.object(obj);
+ case 'array':
+   return s.array(obj);
+   
+ }
+};
+
+JSJaCJSON.parse = function (str) {
+  try {
+    return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
+                                                       str.replace(/"(\\.|[^"\\])*"/g, ''))) &&
+            eval('(' + str + ')');
+    } catch (e) {
+        return false;
+    }
+};
+
+
+/**
+ * @fileoverview This file contains all things that make life easier when
+ * dealing with JIDs
+ * @author Stefan Strigler
+ * @version $Revision$
+ */
+
+/**
+ * list of forbidden chars for nodenames
+ * @private
+ */
+var JSJACJID_FORBIDDEN = ['"',' ','&','\'','/',':','<','>','@'];
+
+/**
+ * Creates a new JSJaCJID object
+ * @class JSJaCJID models xmpp jid objects
+ * @constructor
+ * @param {Object} jid jid may be either of type String or a JID represented
+ * by JSON with fields 'node', 'domain' and 'resource'
+ * @throws JSJaCJIDInvalidException Thrown if jid is not valid
+ * @return a new JSJaCJID object
+ */
+function JSJaCJID(jid) {
+  /**
+   *@private
+   */
+  this._node = '';
+  /**
+   *@private
+   */
+  this._domain = '';
+  /**
+   *@private
+   */
+  this._resource = '';
+
+  if (typeof(jid) == 'string') {
+    if (jid.indexOf('@') != -1) {
+        this.setNode(jid.substring(0,jid.indexOf('@')));
+        jid = jid.substring(jid.indexOf('@')+1);
+    }
+    if (jid.indexOf('/') != -1) {
+      this.setResource(jid.substring(jid.indexOf('/')+1));
+      jid = jid.substring(0,jid.indexOf('/'));
+    }
+    this.setDomain(jid);
+  } else {
+    this.setNode(jid.node);
+    this.setDomain(jid.domain);
+    this.setResource(jid.resource);
+  }
+}
+
+
+/**
+ * Gets the node part of the jid
+ * @return A string representing the node name
+ * @type String
+ */
+JSJaCJID.prototype.getNode = function() { return this._node; };
+
+/**
+ * Gets the domain part of the jid
+ * @return A string representing the domain name
+ * @type String
+ */
+JSJaCJID.prototype.getDomain = function() { return this._domain; };
+
+/**
+ * Gets the resource part of the jid
+ * @return A string representing the resource
+ * @type String
+ */
+JSJaCJID.prototype.getResource = function() { return this._resource; };
+
+
+/**
+ * Sets the node part of the jid
+ * @param {String} node Name of the node
+ * @throws JSJaCJIDInvalidException Thrown if node name contains invalid chars
+ * @return This object
+ * @type JSJaCJID
+ */
+JSJaCJID.prototype.setNode = function(node) {
+  JSJaCJID._checkNodeName(node);
+  this._node = node || '';
+  return this;
+};
+
+/**
+ * Sets the domain part of the jid
+ * @param {String} domain Name of the domain
+ * @throws JSJaCJIDInvalidException Thrown if domain name contains invalid
+ * chars or is empty
+ * @return This object
+ * @type JSJaCJID
+ */
+JSJaCJID.prototype.setDomain = function(domain) {
+  if (!domain || domain == '')
+    throw new JSJaCJIDInvalidException("domain name missing");
+  // chars forbidden for a node are not allowed in domain names
+  // anyway, so let's check
+  JSJaCJID._checkNodeName(domain);
+  this._domain = domain;
+  return this;
+};
+
+/**
+ * Sets the resource part of the jid
+ * @param {String} resource Name of the resource
+ * @return This object
+ * @type JSJaCJID
+ */
+JSJaCJID.prototype.setResource = function(resource) {
+  this._resource = resource || '';
+  return this;
+};
+
+/**
+ * The string representation of the full jid
+ * @return A string representing the jid
+ * @type String
+ */
+JSJaCJID.prototype.toString = function() {
+  var jid = '';
+  if (this.getNode() && this.getNode() != '')
+    jid = this.getNode() + '@';
+  jid += this.getDomain(); // we always have a domain
+  if (this.getResource() && this.getResource() != "")
+    jid += '/' + this.getResource();
+  return jid;
+};
+
+/**
+ * Removes the resource part of the jid
+ * @return This object
+ * @type JSJaCJID
+ */
+JSJaCJID.prototype.removeResource = function() {
+  return this.setResource();
+};
+
+/**
+ * creates a copy of this JSJaCJID object
+ * @return A copy of this
+ * @type JSJaCJID
+ */
+JSJaCJID.prototype.clone = function() {
+  return new JSJaCJID(this.toString());
+};
+
+/**
+ * Compares two jids if they belong to the same entity (i.e. w/o resource)
+ * @param {String} jid a jid as string or JSJaCJID object
+ * @return 'true' if jid is same entity as this
+ * @type Boolean
+ */
+JSJaCJID.prototype.isEntity = function(jid) {
+  if (typeof jid == 'string')
+         jid = (new JSJaCJID(jid));
+  jid.removeResource();
+  return (this.clone().removeResource().toString() === jid.toString());
+};
+
+/**
+ * Check if node name is valid
+ * @private
+ * @param {String} node A name for a node
+ * @throws JSJaCJIDInvalidException Thrown if name for node is not allowed
+ */
+JSJaCJID._checkNodeName = function(nodeprep) {
+    if (!nodeprep || nodeprep == '')
+      return;
+    for (var i=0; i< JSJACJID_FORBIDDEN.length; i++) {
+      if (nodeprep.indexOf(JSJACJID_FORBIDDEN[i]) != -1) {
+        throw new JSJaCJIDInvalidException("forbidden char in nodename: "+JSJACJID_FORBIDDEN[i]);
+      }
+    }
+};
+
+/**
+ * Creates a new Exception of type JSJaCJIDInvalidException
+ * @class Exception to indicate invalid values for a jid
+ * @constructor
+ * @param {String} message The message associated with this Exception
+ */
+function JSJaCJIDInvalidException(message) {
+  /**
+   * The exceptions associated message
+   * @type String
+   */
+  this.message = message;
+  /**
+   * The name of the exception
+   * @type String
+   */
+  this.name = "JSJaCJIDInvalidException";
+}
+
+
+/* Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/**
+ * @private
+ * This code is taken from {@link
+ * http://wiki.script.aculo.us/scriptaculous/show/Builder
+ * script.aculo.us' Dom Builder} and has been modified to suit our
+ * needs.<br/>
+ * The original parts of the code do have the following
+ * copyright and license notice:<br/>
+ * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us,
+ * http://mir.acu lo.us) <br/>
+ * script.aculo.us is freely distributable under the terms of an
+ * MIT-style license.<br>
+ * For details, see the script.aculo.us web site:
+ * http://script.aculo.us/<br>
+ */
+var JSJaCBuilder = {
+  /**
+   * @private
+   */
+  buildNode: function(doc, elementName) {
+
+    var element, ns = arguments[4];
+
+    // attributes (or text)
+    if(arguments[2])
+      if(JSJaCBuilder._isStringOrNumber(arguments[2]) ||
+         (arguments[2] instanceof Array)) {
+        element = this._createElement(doc, elementName, ns);
+        JSJaCBuilder._children(doc, element, arguments[2]);
+      } else {
+        ns = arguments[2]['xmlns'] || ns;
+        element = this._createElement(doc, elementName, ns);
+        for(attr in arguments[2]) {
+          if (arguments[2].hasOwnProperty(attr) && attr != 'xmlns')
+            element.setAttribute(attr, arguments[2][attr]);
+        }
+      }
+    else
+      element = this._createElement(doc, elementName, ns);
+    // text, or array of children
+    if(arguments[3])
+      JSJaCBuilder._children(doc, element, arguments[3], ns);
+
+    return element;
+  },
+
+  _createElement: function(doc, elementName, ns) {
+    try {
+      if (ns)
+        return doc.createElementNS(ns, elementName);
+    } catch (ex) { }
+
+    var el = doc.createElement(elementName);
+
+    if (ns)
+      el.setAttribute("xmlns", ns);
+
+    return el;
+  },
+
+  /**
+   * @private
+   */
+  _text: function(doc, text) {
+    return doc.createTextNode(text);
+  },
+
+  /**
+   * @private
+   */
+  _children: function(doc, element, children, ns) {
+    if(typeof children=='object') { // array can hold nodes and text
+      for (var i in children) {
+        if (children.hasOwnProperty(i)) {
+          var e = children[i];
+          if (typeof e=='object') {
+            if (e instanceof Array) {
+              var node = JSJaCBuilder.buildNode(doc, e[0], e[1], e[2], ns);
+              element.appendChild(node);
+            } else {
+              element.appendChild(e);
+            }
+          } else {
+            if(JSJaCBuilder._isStringOrNumber(e)) {
+              element.appendChild(JSJaCBuilder._text(doc, e));
+            }
+          }
+        }
+      }
+    } else {
+      if(JSJaCBuilder._isStringOrNumber(children)) {
+        element.appendChild(JSJaCBuilder._text(doc, children));
+      }
+    }
+  },
+
+  _attributes: function(attributes) {
+    var attrs = [];
+    for(attribute in attributes)
+      if (attributes.hasOwnProperty(attribute))
+        attrs.push(attribute +
+          '="' + attributes[attribute].toString().htmlEnc() + '"');
+    return attrs.join(" ");
+  },
+
+  _isStringOrNumber: function(param) {
+    return(typeof param=='string' || typeof param=='number');
+  }
+};
+
+
+/**
+ * @fileoverview Contains all Jabber/XMPP packet related classes.
+ * @author Stefan Strigler steve@zeank.in-berlin.de
+ * @version $Revision$
+ */
+
+var JSJACPACKET_USE_XMLNS = true;
+
+/**
+ * Creates a new packet with given root tag name (for internal use)
+ * @class Somewhat abstract base class for all kinds of specialised packets
+ * @param {String} name The root tag name of the packet
+ * (i.e. one of 'message', 'iq' or 'presence')
+ */
+function JSJaCPacket(name) {
+  /**
+   * @private
+   */
+  this.name = name;
+
+  if (typeof(JSJACPACKET_USE_XMLNS) != 'undefined' && JSJACPACKET_USE_XMLNS)
+    /**
+     * @private
+     */
+    this.doc = XmlDocument.create(name,'jabber:client');
+  else
+    /**
+     * @private
+     */
+    this.doc = XmlDocument.create(name,'');
+}
+
+/**
+ * Gets the type (name of root element) of this packet, i.e. one of
+ * 'presence', 'message' or 'iq'
+ * @return the top level tag name
+ * @type String
+ */
+JSJaCPacket.prototype.pType = function() { return this.name; };
+
+/**
+ * Gets the associated Document for this packet.
+ * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document Document}
+ */
+JSJaCPacket.prototype.getDoc = function() {
+  return this.doc;
+};
+/**
+ * Gets the root node of this packet
+ * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node}
+ */
+JSJaCPacket.prototype.getNode = function() {
+  if (this.getDoc() && this.getDoc().documentElement)
+    return this.getDoc().documentElement;
+  else
+    return null;
+};
+
+/**
+ * Sets the 'to' attribute of the root node of this packet
+ * @param {String} to
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.setTo = function(to) {
+  if (!to || to == '')
+    this.getNode().removeAttribute('to');
+  else if (typeof(to) == 'string')
+    this.getNode().setAttribute('to',to);
+  else
+    this.getNode().setAttribute('to',to.toString());
+  return this;
+};
+/**
+ * Sets the 'from' attribute of the root node of this
+ * packet. Usually this is not needed as the server will take care
+ * of this automatically.
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.setFrom = function(from) {
+  if (!from || from == '')
+    this.getNode().removeAttribute('from');
+  else if (typeof(from) == 'string')
+    this.getNode().setAttribute('from',from);
+  else
+    this.getNode().setAttribute('from',from.toString());
+  return this;
+};
+/**
+ * Sets 'id' attribute of the root node of this packet.
+ * @param {String} id The id of the packet.
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.setID = function(id) {
+  if (!id || id == '')
+    this.getNode().removeAttribute('id');
+  else
+    this.getNode().setAttribute('id',id);
+  return this;
+};
+/**
+ * Sets the 'type' attribute of the root node of this packet.
+ * @param {String} type The type of the packet.
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.setType = function(type) {
+  if (!type || type == '')
+    this.getNode().removeAttribute('type');
+  else
+    this.getNode().setAttribute('type',type);
+  return this;
+};
+/**
+ * Sets 'xml:lang' for this packet
+ * @param {String} xmllang The xml:lang of the packet.
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.setXMLLang = function(xmllang) {
+  // Fix IE9+ bug with xml:lang attribute
+  if (BrowserDetect && (BrowserDetect.browser == 'Explorer') && (BrowserDetect.version >= 9))
+    return this;
+  if (!xmllang || xmllang == '')
+    this.getNode().removeAttribute('xml:lang');
+  else
+    this.getNode().setAttribute('xml:lang',xmllang);
+  return this;
+};
+
+/**
+ * Gets the 'to' attribute of this packet
+ * @type String
+ */
+JSJaCPacket.prototype.getTo = function() {
+  return this.getNode().getAttribute('to');
+};
+/**
+ * Gets the 'from' attribute of this packet.
+ * @type String
+ */
+JSJaCPacket.prototype.getFrom = function() {
+  return this.getNode().getAttribute('from');
+};
+/**
+ * Gets the 'to' attribute of this packet as a JSJaCJID object
+ * @type JSJaCJID
+ */
+JSJaCPacket.prototype.getToJID = function() {
+  return new JSJaCJID(this.getTo());
+};
+/**
+ * Gets the 'from' attribute of this packet as a JSJaCJID object
+ * @type JSJaCJID
+ */
+JSJaCPacket.prototype.getFromJID = function() {
+  return new JSJaCJID(this.getFrom());
+};
+/**
+ * Gets the 'id' of this packet
+ * @type String
+ */
+JSJaCPacket.prototype.getID = function() {
+  return this.getNode().getAttribute('id');
+};
+/**
+ * Gets the 'type' of this packet
+ * @type String
+ */
+JSJaCPacket.prototype.getType = function() {
+  return this.getNode().getAttribute('type');
+};
+/**
+ * Gets the 'xml:lang' of this packet
+ * @type String
+ */
+JSJaCPacket.prototype.getXMLLang = function() {
+  return this.getNode().getAttribute('xml:lang');
+};
+/**
+ * Gets the 'xmlns' (xml namespace) of the root node of this packet
+ * @type String
+ */
+JSJaCPacket.prototype.getXMLNS = function() {
+  return this.getNode().namespaceURI || this.getNode().getAttribute('xmlns');
+};
+
+/**
+ * Gets a child element of this packet. If no params given returns first child.
+ * @param {String} name Tagname of child to retrieve. Use '*' to match any tag. [optional]
+ * @param {String} ns   Namespace of child. Use '*' to match any ns.[optional]
+ * @return The child node, null if none found
+ * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node}
+ */
+JSJaCPacket.prototype.getChild = function(name, ns) {
+  if (!this.getNode()) {
+    return null;
+  }
+
+  name = name || '*';
+  ns = ns || '*';
+
+  if (this.getNode().getElementsByTagNameNS) {
+    return this.getNode().getElementsByTagNameNS(ns, name).item(0);
+  }
+
+  // fallback
+  var nodes = this.getNode().getElementsByTagName(name);
+  if (ns != '*') {
+    for (var i=0; i<nodes.length; i++) {
+      if (nodes.item(i).namespaceURI == ns || nodes.item(i).getAttribute('xmlns') == ns) {
+        return nodes.item(i);
+      }
+    }
+  } else {
+    return nodes.item(0);
+  }
+  return null; // nothing found
+};
+
+/**
+ * Gets the node value of a child element of this packet.
+ * @param {String} name Tagname of child to retrieve.
+ * @param {String} ns   Namespace of child
+ * @return The value of the child node, empty string if none found
+ * @type String
+ */
+JSJaCPacket.prototype.getChildVal = function(name, ns) {
+  var node = this.getChild(name, ns);
+  var ret = '';
+  if (node && node.hasChildNodes()) {
+    // concatenate all values from childNodes
+    for (var i=0; i<node.childNodes.length; i++)
+      if (node.childNodes.item(i).nodeValue)
+        ret += node.childNodes.item(i).nodeValue;
+  }
+  return ret;
+};
+
+/**
+ * Returns a copy of this node
+ * @return a copy of this node
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.clone = function() {
+  return JSJaCPacket.wrapNode(this.getNode());
+};
+
+/**
+ * Checks if packet is of type 'error'
+ * @return 'true' if this packet is of type 'error', 'false' otherwise
+ * @type boolean
+ */
+JSJaCPacket.prototype.isError = function() {
+  return (this.getType() == 'error');
+};
+
+/**
+ * Returns an error condition reply according to {@link http://www.xmpp.org/extensions/xep-0086.html XEP-0086}. Creates a clone of the calling packet with senders and recipient exchanged and error stanza appended.
+ * @param {STANZA_ERROR} stanza_error an error stanza containing error cody, type and condition of the error to be indicated
+ * @return an error reply packet
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.errorReply = function(stanza_error) {
+  var rPacket = this.clone();
+  rPacket.setTo(this.getFrom());
+  rPacket.setFrom();
+  rPacket.setType('error');
+
+  rPacket.appendNode('error',
+                     {code: stanza_error.code, type: stanza_error.type},
+                     [[stanza_error.cond]]);
+
+  return rPacket;
+};
+
+/**
+ * Returns a string representation of the raw xml content of this packet.
+ * @type String
+ */
+JSJaCPacket.prototype.xml = typeof XMLSerializer != 'undefined' ?
+function() {
+  var r = (new XMLSerializer()).serializeToString(this.getNode());
+  if (typeof(r) == 'undefined')
+    r = (new XMLSerializer()).serializeToString(this.doc); // oldschool
+  return r
+} :
+function() {// IE
+  return this.getDoc().xml
+};
+
+
+// PRIVATE METHODS DOWN HERE
+
+/**
+ * Gets an attribute of the root element
+ * @private
+ */
+JSJaCPacket.prototype._getAttribute = function(attr) {
+  return this.getNode().getAttribute(attr);
+};
+
+
+if (document.ELEMENT_NODE == null) {
+  document.ELEMENT_NODE = 1;
+  document.ATTRIBUTE_NODE = 2;
+  document.TEXT_NODE = 3;
+  document.CDATA_SECTION_NODE = 4;
+  document.ENTITY_REFERENCE_NODE = 5;
+  document.ENTITY_NODE = 6;
+  document.PROCESSING_INSTRUCTION_NODE = 7;
+  document.COMMENT_NODE = 8;
+  document.DOCUMENT_NODE = 9;
+  document.DOCUMENT_TYPE_NODE = 10;
+  document.DOCUMENT_FRAGMENT_NODE = 11;
+  document.NOTATION_NODE = 12;
+}
+
+/**
+ * import node into this packets document
+ * @private
+ */
+JSJaCPacket.prototype._importNode = function(node, allChildren) {
+  switch (node.nodeType) {
+  case document.ELEMENT_NODE:
+
+  if (this.getDoc().createElementNS) {
+    var newNode = this.getDoc().createElementNS(node.namespaceURI, node.nodeName);
+  } else {
+    var newNode = this.getDoc().createElement(node.nodeName);
+  }
+
+  /* does the node have any attributes to add? */
+  if (node.attributes && node.attributes.length > 0)
+    for (var i = 0, il = node.attributes.length;i < il; i++) {
+      var attr = node.attributes.item(i);
+      if (attr.nodeName == 'xmlns' && newNode.getAttribute('xmlns') != null ) continue;
+      if (newNode.setAttributeNS && attr.namespaceURI) {
+        newNode.setAttributeNS(attr.namespaceURI,
+                               attr.nodeName,
+                               attr.nodeValue);
+      } else {
+        newNode.setAttribute(attr.nodeName,
+                             attr.nodeValue);
+      }
+    }
+  /* are we going after children too, and does the node have any? */
+  if (allChildren && node.childNodes && node.childNodes.length > 0) {
+    for (var i = 0, il = node.childNodes.length; i < il; i++) {
+      newNode.appendChild(this._importNode(node.childNodes.item(i), allChildren));
+    }
+  }
+  return newNode;
+  break;
+  case document.TEXT_NODE:
+  case document.CDATA_SECTION_NODE:
+  case document.COMMENT_NODE:
+  return this.getDoc().createTextNode(node.nodeValue);
+  break;
+  }
+};
+
+/**
+ * Set node value of a child node
+ * @private
+ */
+JSJaCPacket.prototype._setChildNode = function(nodeName, nodeValue) {
+  var aNode = this.getChild(nodeName);
+  var tNode = this.getDoc().createTextNode(nodeValue);
+  if (aNode)
+    try {
+      aNode.replaceChild(tNode,aNode.firstChild);
+    } catch (e) { }
+  else {
+    try {
+      aNode = this.getDoc().createElementNS(this.getNode().namespaceURI,
+                                            nodeName);
+    } catch (ex) {
+      aNode = this.getDoc().createElement(nodeName)
+    }
+    this.getNode().appendChild(aNode);
+    aNode.appendChild(tNode);
+  }
+  return aNode;
+};
+
+/**
+ * Builds a node using {@link
+ * http://wiki.script.aculo.us/scriptaculous/show/Builder
+ * script.aculo.us' Dom Builder} notation.
+ * This code is taken from {@link
+ * http://wiki.script.aculo.us/scriptaculous/show/Builder
+ * script.aculo.us' Dom Builder} and has been modified to suit our
+ * needs.<br/>
+ * The original parts of the code do have the following copyright
+ * and license notice:<br/>
+ * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us,
+ * http://mir.acu lo.us) <br/>
+ * script.aculo.us is freely distributable under the terms of an
+ * MIT-style licen se.  // For details, see the script.aculo.us web
+ * site: http://script.aculo.us/<br>
+ * @author Thomas Fuchs
+ * @author Stefan Strigler
+ * @return The newly created node
+ * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node}
+ */
+JSJaCPacket.prototype.buildNode = function(elementName) {
+  return JSJaCBuilder.buildNode(this.getDoc(),
+                                elementName,
+                                arguments[1],
+                                arguments[2]);
+};
+
+/**
+ * Appends node created by buildNode to this packets parent node.
+ * @param {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} element The node to append or
+ * @param {String} element A name plus an object hash with attributes (optional) plus an array of childnodes (optional)
+ * @see #buildNode
+ * @return This packet
+ * @type JSJaCPacket
+ */
+JSJaCPacket.prototype.appendNode = function(element) {
+  if (typeof element=='object') { // seems to be a prebuilt node
+    return this.getNode().appendChild(element)
+  } else { // build node
+    return this.getNode().appendChild(this.buildNode(element,
+                                                     arguments[1],
+                                                     arguments[2],
+                                                     null,
+                                                     this.getNode().namespaceURI));
+  }
+};
+
+
+/**
+ * A jabber/XMPP presence packet
+ * @class Models the XMPP notion of a 'presence' packet
+ * @extends JSJaCPacket
+ */
+function JSJaCPresence() {
+  /**
+   * @ignore
+   */
+  this.base = JSJaCPacket;
+  this.base('presence');
+}
+JSJaCPresence.prototype = new JSJaCPacket;
+
+/**
+ * Sets the status message for current status. Usually this is set
+ * to some human readable string indicating what the user is
+ * doing/feel like currently.
+ * @param {String} status A status message
+ * @return this
+ * @type JSJaCPacket
+ */
+JSJaCPresence.prototype.setStatus = function(status) {
+  this._setChildNode("status", status);
+  return this;
+};
+/**
+ * Sets the online status for this presence packet.
+ * @param {String} show An XMPP complient status indicator. Must
+ * be one of 'chat', 'away', 'xa', 'dnd'
+ * @return this
+ * @type JSJaCPacket
+ */
+JSJaCPresence.prototype.setShow = function(show) {
+  if (show == 'chat' || show == 'away' || show == 'xa' || show == 'dnd')
+    this._setChildNode("show",show);
+  return this;
+};
+/**
+ * Sets the priority of the resource bind to with this connection
+ * @param {int} prio The priority to set this resource to
+ * @return this
+ * @type JSJaCPacket
+ */
+JSJaCPresence.prototype.setPriority = function(prio) {
+  this._setChildNode("priority", prio);
+  return this;
+};
+/**
+ * Some combined method that allowes for setting show, status and
+ * priority at once
+ * @param {String} show A status message
+ * @param {String} status A status indicator as defined by XMPP
+ * @param {int} prio A priority for this resource
+ * @return this
+ * @type JSJaCPacket
+ */
+JSJaCPresence.prototype.setPresence = function(show,status,prio) {
+  if (show)
+    this.setShow(show);
+  if (status)
+    this.setStatus(status);
+  if (prio)
+    this.setPriority(prio);
+  return this;
+};
+
+/**
+ * Gets the status message of this presence
+ * @return The (human readable) status message
+ * @type String
+ */
+JSJaCPresence.prototype.getStatus = function() {
+  return this.getChildVal('status');
+};
+/**
+ * Gets the status of this presence.
+ * Either one of 'chat', 'away', 'xa' or 'dnd' or null.
+ * @return The status indicator as defined by XMPP
+ * @type String
+ */
+JSJaCPresence.prototype.getShow = function() {
+  return this.getChildVal('show');
+};
+/**
+ * Gets the priority of this status message
+ * @return A resource priority
+ * @type int
+ */
+JSJaCPresence.prototype.getPriority = function() {
+  return this.getChildVal('priority');
+};
+
+
+/**
+ * A jabber/XMPP iq packet
+ * @class Models the XMPP notion of an 'iq' packet
+ * @extends JSJaCPacket
+ */
+function JSJaCIQ() {
+  /**
+   * @ignore
+   */
+  this.base = JSJaCPacket;
+  this.base('iq');
+}
+JSJaCIQ.prototype = new JSJaCPacket;
+
+/**
+ * Some combined method to set 'to', 'type' and 'id' at once
+ * @param {String} to the recepients JID
+ * @param {String} type A XMPP compliant iq type (one of 'set', 'get', 'result' and 'error'
+ * @param {String} id A packet ID
+ * @return this
+ * @type JSJaCIQ
+ */
+JSJaCIQ.prototype.setIQ = function(to,type,id) {
+  if (to)
+    this.setTo(to);
+  if (type)
+    this.setType(type);
+  if (id)
+    this.setID(id);
+  return this;
+};
+/**
+ * Creates a 'query' child node with given XMLNS
+ * @param {String} xmlns The namespace for the 'query' node
+ * @return The query node
+ * @type {@link  http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node}
+ */
+JSJaCIQ.prototype.setQuery = function(xmlns) {
+  var query;
+  try {
+    query = this.getDoc().createElementNS(xmlns,'query');
+  } catch (e) {
+    query = this.getDoc().createElement('query');
+       query.setAttribute('xmlns',xmlns);
+  }
+  this.getNode().appendChild(query);
+  return query;
+};
+
+/**
+ * Gets the 'query' node of this packet
+ * @return The query node
+ * @type {@link  http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node}
+ */
+JSJaCIQ.prototype.getQuery = function() {
+  return this.getNode().getElementsByTagName('query').item(0);
+};
+/**
+ * Gets the XMLNS of the query node contained within this packet
+ * @return The namespace of the query node
+ * @type String
+ */
+JSJaCIQ.prototype.getQueryXMLNS = function() {
+  if (this.getQuery()) {
+    return this.getQuery().namespaceURI || this.getQuery().getAttribute('xmlns');
+  } else {
+    return null;
+  }
+};
+
+/**
+ * Creates an IQ reply with type set to 'result'. If given appends payload to first child if IQ. Payload maybe XML as string or a DOM element (or an array of such elements as well).
+ * @param {Element} payload A payload to be appended [optional]
+ * @return An IQ reply packet
+ * @type JSJaCIQ
+ */
+JSJaCIQ.prototype.reply = function(payload) {
+  var rIQ = this.clone();
+  rIQ.setTo(this.getFrom());
+  rIQ.setFrom();
+  rIQ.setType('result');
+  if (payload) {
+    if (typeof payload == 'string')
+      rIQ.getChild().appendChild(rIQ.getDoc().loadXML(payload));
+    else if (payload.constructor == Array) {
+      var node = rIQ.getChild();
+      for (var i=0; i<payload.length; i++)
+        if(typeof payload[i] == 'string')
+          node.appendChild(rIQ.getDoc().loadXML(payload[i]));
+        else if (typeof payload[i] == 'object')
+          node.appendChild(payload[i]);
+    }
+    else if (typeof payload == 'object')
+      rIQ.getChild().appendChild(payload);
+  }
+  return rIQ;
+};
+
+/**
+ * A jabber/XMPP message packet
+ * @class Models the XMPP notion of an 'message' packet
+ * @extends JSJaCPacket
+ */
+function JSJaCMessage() {
+  /**
+   * @ignore
+   */
+  this.base = JSJaCPacket;
+  this.base('message');
+}
+JSJaCMessage.prototype = new JSJaCPacket;
+
+/**
+ * Sets the body of the message
+ * @param {String} body Your message to be sent along
+ * @return this message
+ * @type JSJaCMessage
+ */
+JSJaCMessage.prototype.setBody = function(body) {
+  this._setChildNode("body",body);
+  return this;
+};
+/**
+ * Sets the subject of the message
+ * @param {String} subject Your subject to be sent along
+ * @return this message
+ * @type JSJaCMessage
+ */
+JSJaCMessage.prototype.setSubject = function(subject) {
+  this._setChildNode("subject",subject);
+  return this;
+};
+/**
+ * Sets the 'tread' attribute for this message. This is used to identify
+ * threads in chat conversations
+ * @param {String} thread Usually a somewhat random hash.
+ * @return this message
+ * @type JSJaCMessage
+ */
+JSJaCMessage.prototype.setThread = function(thread) {
+  this._setChildNode("thread", thread);
+  return this;
+};
+/**
+ * Gets the 'thread' identifier for this message
+ * @return A thread identifier
+ * @type String
+ */
+JSJaCMessage.prototype.getThread = function() {
+  return this.getChildVal('thread');
+};
+/**
+ * Gets the body of this message
+ * @return The body of this message
+ * @type String
+ */
+JSJaCMessage.prototype.getBody = function() {
+  return this.getChildVal('body');
+};
+/**
+ * Gets the subject of this message
+ * @return The subject of this message
+ * @type String
+ */
+JSJaCMessage.prototype.getSubject = function() {
+  return this.getChildVal('subject')
+};
+
+
+/**
+ * Tries to transform a w3c DOM node to JSJaC's internal representation
+ * (JSJaCPacket type, one of JSJaCPresence, JSJaCMessage, JSJaCIQ)
+ * @param: {Node
+ * http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247}
+ * node The node to be transformed
+ * @return A JSJaCPacket representing the given node. If node's root
+ * elemenent is not one of 'message', 'presence' or 'iq',
+ * <code>null</code> is being returned.
+ * @type JSJaCPacket
+ */
+JSJaCPacket.wrapNode = function(node) {
+  var oPacket = null;
+
+  switch (node.nodeName.toLowerCase()) {
+  case 'presence':
+      oPacket = new JSJaCPresence();
+      break;
+  case 'message':
+      oPacket = new JSJaCMessage();
+      break;
+  case 'iq':
+      oPacket = new JSJaCIQ();
+      break;
+  }
+
+  if (oPacket) {
+    oPacket.getDoc().replaceChild(oPacket._importNode(node, true),
+                                  oPacket.getNode());
+  }
+
+  return oPacket;
+};
+
+
+
+/**
+ * an error packet for internal use
+ * @private
+ * @constructor
+ */
+function JSJaCError(code,type,condition) {
+  var xmldoc = XmlDocument.create("error","jsjac");
+
+  xmldoc.documentElement.setAttribute('code',code);
+  xmldoc.documentElement.setAttribute('type',type);
+  if (condition)
+    xmldoc.documentElement.appendChild(xmldoc.createElement(condition)).
+      setAttribute('xmlns','urn:ietf:params:xml:ns:xmpp-stanzas');
+  return xmldoc.documentElement;
+}
+
+
+
+/**
+ * Creates a new set of hash keys
+ * @class Reflects a set of sha1/md5 hash keys for securing sessions
+ * @constructor
+ * @param {Function} func The hash function to be used for creating the keys
+ * @param {Debugger} oDbg Reference to debugger implementation [optional]
+ */                                                                     
+function JSJaCKeys(func,oDbg) {
+  var seed = Math.random();
+
+  /**
+   * @private
+   */
+  this._k = new Array();
+  this._k[0] = seed.toString();
+  if (oDbg)
+    /**
+     * Reference to Debugger
+     * @type Debugger
+     */
+    this.oDbg = oDbg;
+  else {
+    this.oDbg = {};
+    this.oDbg.log = function() {};
+  }
+
+  if (func) {
+    for (var i=1; i<JSJAC_NKEYS; i++) {
+      this._k[i] = func(this._k[i-1]);
+      oDbg.log(i+": "+this._k[i],4);
+    }
+  }
+
+  /**
+   * @private
+   */
+  this._indexAt = JSJAC_NKEYS-1;
+  /**
+   * Gets next key from stack
+   * @return New hash key
+   * @type String
+   */
+  this.getKey = function() {
+    return this._k[this._indexAt--];
+  };
+  /**
+   * Indicates whether there's only one key left
+   * @return <code>true</code> if there's only one key left, false otherwise
+   * @type boolean
+   */
+  this.lastKey = function() { return (this._indexAt == 0); };
+  /**
+   * Returns number of overall/initial stack size
+   * @return Number of keys created
+   * @type int
+   */
+  this.size = function() { return this._k.length; };
+
+  /**
+   * @private
+   */
+  this._getSuspendVars = function() {
+    return ('_k,_indexAt').split(',');
+  }
+}
+
+
+/**
+ * @fileoverview Contains all things in common for all subtypes of connections
+ * supported.
+ * @author Stefan Strigler steve@zeank.in-berlin.de
+ * @version $Revision$
+ */
+
+/**
+ * Creates a new Jabber connection (a connection to a jabber server)
+ * @class Somewhat abstract base class for jabber connections. Contains all
+ * of the code in common for all jabber connections
+ * @constructor
+ * @param {JSON http://www.json.org/index} oArg JSON with properties: <br>
+ * * <code>httpbase</code> the http base address of the service to be used for
+ * connecting to jabber<br>
+ * * <code>oDbg</code> (optional) a reference to a debugger interface
+ */
+function JSJaCConnection(oArg) {
+
+  if (oArg && oArg.oDbg && oArg.oDbg.log) {
+      /**
+       * Reference to debugger interface
+       * (needs to implement method <code>log</code>)
+       * @type Debugger
+       */
+    this.oDbg = oArg.oDbg;
+  } else {
+    this.oDbg = new Object(); // always initialise a debugger
+    this.oDbg.log = function() { };
+  }
+
+  if (oArg && oArg.timerval)
+    this.setPollInterval(oArg.timerval);
+  else
+    this.setPollInterval(JSJAC_TIMERVAL);
+
+  if (oArg && oArg.httpbase)
+      /**
+       * @private
+       */
+    this._httpbase = oArg.httpbase;
+
+  if (oArg &&oArg.allow_plain)
+      /**
+       * @private
+       */
+    this.allow_plain = oArg.allow_plain;
+  else
+    this.allow_plain = JSJAC_ALLOW_PLAIN;
+
+  if (oArg && oArg.cookie_prefix)
+      /**
+       * @private
+       */
+    this._cookie_prefix = oArg.cookie_prefix;
+  else
+    this._cookie_prefix = "";
+
+  /**
+   * @private
+   */
+  this._connected = false;
+  /**
+   * @private
+   */
+  this._events = new Array();
+  /**
+   * @private
+   */
+  this._keys = null;
+  /**
+   * @private
+   */
+  this._ID = 0;
+  /**
+   * @private
+   */
+  this._inQ = new Array();
+  /**
+   * @private
+   */
+  this._pQueue = new Array();
+  /**
+   * @private
+   */
+  this._regIDs = new Array();
+  /**
+   * @private
+   */
+  this._req = new Array();
+  /**
+   * @private
+   */
+  this._status = 'intialized';
+  /**
+   * @private
+   */
+  this._errcnt = 0;
+  /**
+   * @private
+   */
+  this._inactivity = JSJAC_INACTIVITY;
+  /**
+   * @private
+   */
+  this._sendRawCallbacks = new Array();
+}
+
+// Generates an ID
+var STANZA_ID = 1;
+
+function genID() {
+  return STANZA_ID++;
+}
+
+JSJaCConnection.prototype.connect = function(oArg) {
+    this._setStatus('connecting');
+
+    this.domain = oArg.domain || 'localhost';
+    this.username = oArg.username;
+    this.resource = oArg.resource;
+    this.pass = oArg.pass;
+    this.register = oArg.register;
+
+    this.authhost = oArg.authhost || this.domain;
+    this.authtype = oArg.authtype || 'sasl';
+
+    if (oArg.xmllang && oArg.xmllang != '')
+        this._xmllang = oArg.xmllang;
+    else
+        this._xmllang = 'en';
+
+    this.host = oArg.host || this.domain;
+    this.port = oArg.port || 5222;
+    if (oArg.secure)
+        this.secure = 'true';
+    else
+        this.secure = 'false';
+
+    if (oArg.wait)
+        this._wait = oArg.wait;
+
+    this.jid = this.username + '@' + this.domain;
+    this.fulljid = this.jid + '/' + this.resource;
+
+    this._rid  = Math.round( 100000.5 + ( ( (900000.49999) - (100000.5) ) * Math.random() ) );
+
+    // setupRequest must be done after rid is created but before first use in reqstr
+    var slot = this._getFreeSlot();
+    this._req[slot] = this._setupRequest(true);
+
+    var reqstr = this._getInitialRequestString();
+
+    this.oDbg.log(reqstr,4);
+
+    this._req[slot].r.onreadystatechange =
+        JSJaC.bind(function() {
+            var r = this._req[slot].r;
+            if (r.readyState == 4) {
+                this.oDbg.log("async recv: "+r.responseText,4);
+                this._handleInitialResponse(r); // handle response
+            }
+        }, this);
+
+    if (typeof(this._req[slot].r.onerror) != 'undefined') {
+        this._req[slot].r.onerror =
+            JSJaC.bind(function(e) {
+                this.oDbg.log('XmlHttpRequest error',1);
+                return false;
+            }, this);
+    }
+
+    this._req[slot].r.send(reqstr);
+};
+
+/**
+ * Tells whether this connection is connected
+ * @return <code>true</code> if this connections is connected,
+ * <code>false</code> otherwise
+ * @type boolean
+ */
+JSJaCConnection.prototype.connected = function() { return this._connected; };
+
+/**
+ * Disconnects from jabber server and terminates session (if applicable)
+ */
+JSJaCConnection.prototype.disconnect = function() {
+  this._setStatus('disconnecting');
+  if (!this.connected())
+    return;
+  this._connected = false;
+  clearInterval(this._interval);
+  clearInterval(this._inQto);
+  if (this._timeout)
+    clearTimeout(this._timeout); // remove timer
+  var slot = this._getFreeSlot();
+  // Intentionally synchronous
+  this._req[slot] = this._setupRequest(false);
+  request = this._getRequestString(false, true);
+  this.oDbg.log("Disconnecting: " + request,4);
+  this._req[slot].r.send(request);
+  try {
+    removeDB('jsjac', 'state');
+  } catch (e) {}
+  this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2);
+  this._handleEvent('ondisconnect');
+};
+
+/**
+ * Gets current value of polling interval
+ * @return Polling interval in milliseconds
+ * @type int
+ */
+JSJaCConnection.prototype.getPollInterval = function() {
+  return this._timerval;
+};
+
+/**
+ * Registers an event handler (callback) for this connection.
+
+ * <p>Note: All of the packet handlers for specific packets (like
+ * message_in, presence_in and iq_in) fire only if there's no
+ * callback associated with the id.<br>
+
+ * <p>Example:<br/>
+ * <code>con.registerHandler('iq', 'query', 'jabber:iq:version', handleIqVersion);</code>
+
+
+ * @param {String} event One of
+
+ * <ul>
+ * <li>onConnect - connection has been established and authenticated</li>
+ * <li>onDisconnect - connection has been disconnected</li>
+ * <li>onResume - connection has been resumed</li>
+
+ * <li>onStatusChanged - connection status has changed, current
+ * status as being passed argument to handler. See {@link #status}.</li>
+
+ * <li>onError - an error has occured, error node is supplied as
+ * argument, like this:<br><code>&lt;error code='404' type='cancel'&gt;<br>
+ * &lt;item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&gt;<br>
+ * &lt;/error&gt;</code></li>
+
+ * <li>packet_in - a packet has been received (argument: the
+ * packet)</li>
+
+ * <li>packet_out - a packet is to be sent(argument: the
+ * packet)</li>
+
+ * <li>message_in | message - a message has been received (argument:
+ * the packet)</li>
+
+ * <li>message_out - a message packet is to be sent (argument: the
+ * packet)</li>
+
+ * <li>presence_in | presence - a presence has been received
+ * (argument: the packet)</li>
+
+ * <li>presence_out - a presence packet is to be sent (argument: the
+ * packet)</li>
+
+ * <li>iq_in | iq - an iq has been received (argument: the packet)</li>
+ * <li>iq_out - an iq is to be sent (argument: the packet)</li>
+ * </ul>
+
+ * @param {String} childName A childnode's name that must occur within a
+ * retrieved packet [optional]
+
+ * @param {String} childNS A childnode's namespace that must occure within
+ * a retrieved packet (works only if childName is given) [optional]
+
+ * @param {String} type The type of the packet to handle (works only if childName and chidNS are given (both may be set to '*' in order to get skipped) [optional]
+
+ * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired.
+ */
+JSJaCConnection.prototype.registerHandler = function(event) {
+  event = event.toLowerCase(); // don't be case-sensitive here
+  var eArg = {handler: arguments[arguments.length-1],
+              childName: '*',
+              childNS: '*',
+              type: '*'};
+  if (arguments.length > 2)
+    eArg.childName = arguments[1];
+  if (arguments.length > 3)
+    eArg.childNS = arguments[2];
+  if (arguments.length > 4)
+    eArg.type = arguments[3];
+  if (!this._events[event])
+    this._events[event] = new Array(eArg);
+  else
+    this._events[event] = this._events[event].concat(eArg);
+
+  // sort events in order how specific they match criterias thus using
+  // wildcard patterns puts them back in queue when it comes to
+  // bubbling the event
+  this._events[event] =
+  this._events[event].sort(function(a,b) {
+    var aRank = 0;
+    var bRank = 0;
+    with (a) {
+      if (type == '*')
+        aRank++;
+      if (childNS == '*')
+        aRank++;
+      if (childName == '*')
+        aRank++;
+    }
+    with (b) {
+      if (type == '*')
+        bRank++;
+      if (childNS == '*')
+        bRank++;
+      if (childName == '*')
+        bRank++;
+    }
+    if (aRank > bRank)
+      return 1;
+    if (aRank < bRank)
+      return -1;
+    return 0;
+  });
+  this.oDbg.log("registered handler for event '"+event+"'",2);
+};
+
+JSJaCConnection.prototype.unregisterHandler = function(event,handler) {
+  event = event.toLowerCase(); // don't be case-sensitive here
+
+  if (!this._events[event])
+    return;
+
+  var arr = this._events[event], res = new Array();
+  for (var i=0; i<arr.length; i++)
+    if (arr[i].handler != handler)
+      res.push(arr[i]);
+
+  if (arr.length != res.length) {
+    this._events[event] = res;
+    this.oDbg.log("unregistered handler for event '"+event+"'",2);
+  }
+};
+
+/**
+ * Register for iq packets of type 'get'.
+ * @param {String} childName A childnode's name that must occur within a
+ * retrieved packet
+
+ * @param {String} childNS A childnode's namespace that must occure within
+ * a retrieved packet (works only if childName is given)
+
+ * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired.
+ */
+JSJaCConnection.prototype.registerIQGet = function(childName, childNS, handler) {
+  this.registerHandler('iq', childName, childNS, 'get', handler);
+};
+
+/**
+ * Register for iq packets of type 'set'.
+ * @param {String} childName A childnode's name that must occur within a
+ * retrieved packet
+
+ * @param {String} childNS A childnode's namespace that must occure within
+ * a retrieved packet (works only if childName is given)
+
+ * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired.
+ */
+JSJaCConnection.prototype.registerIQSet = function(childName, childNS, handler) {
+  this.registerHandler('iq', childName, childNS, 'set', handler);
+};
+
+/**
+ * Resumes this connection from saved state (cookie)
+ * @return Whether resume was successful
+ * @type boolean
+ */
+JSJaCConnection.prototype.resume = function() {
+  try {
+    var json = getDB('jsjac', 'state');
+    this.oDbg.log('read cookie: '+json,2);
+    removeDB('jsjac', 'state');
+
+    return this.resumeFromData(JSJaCJSON.parse(json));
+  } catch (e) {}
+  return false; // sth went wrong
+};
+
+/**
+ * Resumes BOSH connection from data
+ * @param {Object} serialized jsjac state information
+ * @return Whether resume was successful
+ * @type boolean
+ */
+JSJaCConnection.prototype.resumeFromData = function(data) {
+  try {
+    this._setStatus('resuming');
+
+    for (var i in data)
+      if (data.hasOwnProperty(i))
+        this[i] = data[i];
+
+    // copy keys - not being very generic here :-/
+    if (this._keys) {
+      this._keys2 = new JSJaCKeys();
+      var u = this._keys2._getSuspendVars();
+      for (var i=0; i<u.length; i++)
+        this._keys2[u[i]] = this._keys[u[i]];
+      this._keys = this._keys2;
+    }
+
+    if (this._connected) {
+      // don't poll too fast!
+      this._handleEvent('onresume');
+      setTimeout(JSJaC.bind(this._resume, this),this.getPollInterval());
+      this._interval = setInterval(JSJaC.bind(this._checkQueue, this),
+                                  JSJAC_CHECKQUEUEINTERVAL);
+      this._inQto = setInterval(JSJaC.bind(this._checkInQ, this),
+                               JSJAC_CHECKINQUEUEINTERVAL);
+    }
+
+    return (this._connected === true);
+  } catch (e) {
+    if (e.message)
+      this.oDbg.log("Resume failed: "+e.message, 1);
+    else
+      this.oDbg.log("Resume failed: "+e, 1);
+    return false;
+  }
+};
+
+/**
+ * Sends a JSJaCPacket
+ * @param {JSJaCPacket} packet  The packet to send
+ * @param {Function}    cb      The callback to be called if there's a reply
+ * to this packet (identified by id) [optional]
+ * @param {Object}      arg     Arguments passed to the callback
+ * (additionally to the packet received) [optional]
+ * @return 'true' if sending was successfull, 'false' otherwise
+ * @type boolean
+ */
+JSJaCConnection.prototype.send = function(packet,cb,arg) {
+  if (!packet || !packet.pType) {
+    this.oDbg.log("no packet: "+packet, 1);
+    return false;
+  }
+
+  if (!this.connected())
+    return false;
+
+  // generate an ID for the packet
+  if (!packet.getID())
+    packet.setID(genID());
+
+  // packet xml:lang
+  if (!packet.getXMLLang())
+    packet.setXMLLang(XML_LANG);
+
+  // remember id for response if callback present
+  if (cb)
+    this._registerPID(packet.getID(),cb,arg);
+
+  try {
+    this._handleEvent(packet.pType()+'_out', packet);
+    this._handleEvent("packet_out", packet);
+    this._pQueue = this._pQueue.concat(packet.xml());
+  } catch (e) {
+    this.oDbg.log(e.toString(),1);
+    return false;
+  }
+
+  return true;
+};
+
+/**
+ * Sends an IQ packet. Has default handlers for each reply type.
+ * Those maybe overriden by passing an appropriate handler.
+ * @param {JSJaCIQPacket} iq - the iq packet to send
+ * @param {Object} handlers - object with properties 'error_handler',
+ *                            'result_handler' and 'default_handler'
+ *                            with appropriate functions
+ * @param {Object} arg - argument to handlers
+ * @return 'true' if sending was successfull, 'false' otherwise
+ * @type boolean
+ */
+JSJaCConnection.prototype.sendIQ = function(iq, handlers, arg) {
+  if (!iq || iq.pType() != 'iq') {
+    return false;
+  }
+
+  handlers = handlers || {};
+    var error_handler = handlers.error_handler || JSJaC.bind(function(aIq) {
+        this.oDbg.log(aIq.xml(), 1);
+    }, this);
+
+    var result_handler = handlers.result_handler ||  JSJaC.bind(function(aIq) {
+        this.oDbg.log(aIq.xml(), 2);
+    }, this);
+
+  var iqHandler = function(aIq, arg) {
+    switch (aIq.getType()) {
+      case 'error':
+      error_handler(aIq);
+      break;
+      case 'result':
+      result_handler(aIq, arg);
+      break;
+    }
+  };
+  return this.send(iq, iqHandler, arg);
+};
+
+/**
+ * Sets polling interval for this connection
+ * @param {int} millisecs Milliseconds to set timer to
+ * @return effective interval this connection has been set to
+ * @type int
+ */
+JSJaCConnection.prototype.setPollInterval = function(timerval) {
+  if (timerval && !isNaN(timerval))
+    this._timerval = timerval;
+  return this._timerval;
+};
+
+/**
+ * Returns current status of this connection
+ * @return String to denote current state. One of
+ * <ul>
+ * <li>'initializing' ... well
+ * <li>'connecting' if connect() was called
+ * <li>'resuming' if resume() was called
+ * <li>'processing' if it's about to operate as normal
+ * <li>'onerror_fallback' if there was an error with the request object
+ * <li>'protoerror_fallback' if there was an error at the http binding protocol flow (most likely that's where you interested in)
+ * <li>'internal_server_error' in case of an internal server error
+ * <li>'suspending' if suspend() is being called
+ * <li>'aborted' if abort() was called
+ * <li>'disconnecting' if disconnect() has been called
+ * </ul>
+ * @type String
+ */
+JSJaCConnection.prototype.status = function() { return this._status; };
+
+/**
+ * Suspends this connection (saving state for later resume)
+ * Saves state to cookie
+ * @return Whether suspend (saving to cookie) was successful
+ * @type boolean
+ */
+JSJaCConnection.prototype.suspend = function(has_pause) {
+  var data = this.suspendToData(has_pause);
+  
+  try {
+    var c = setDB('jsjac', 'state', JSJaCJSON.toString(data));
+    return c;
+  } catch (e) {
+    this.oDbg.log("Failed creating cookie '"+this._cookie_prefix+
+                  "JSJaC_State': "+e.message,1);
+  }
+  return false;
+};
+
+/**
+ * Suspend connection and return serialized JSJaC connection state
+ * @return JSJaC connection state object
+ * @type Object
+ */
+JSJaCConnection.prototype.suspendToData = function(has_pause) {
+  
+  // remove timers
+  if(has_pause) {
+    clearTimeout(this._timeout);
+    clearInterval(this._interval);
+    clearInterval(this._inQto);
+
+    this._suspend();
+  }
+  
+  var u = ('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(',');
+  u = u.concat(this._getSuspendVars());
+  var s = new Object();
+
+  for (var i=0; i<u.length; i++) {
+    if (!this[u[i]]) continue; // hu? skip these!
+    if (this[u[i]]._getSuspendVars) {
+      var uo = this[u[i]]._getSuspendVars();
+      var o = new Object();
+      for (var j=0; j<uo.length; j++)
+        o[uo[j]] = this[u[i]][uo[j]];
+    } else
+      var o = this[u[i]];
+
+    s[u[i]] = o;
+  }
+  
+  if(has_pause) {
+    this._connected = false;
+    this._setStatus('suspending');
+  }
+  
+  return s;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._abort = function() {
+  clearTimeout(this._timeout); // remove timer
+
+  clearInterval(this._inQto);
+  clearInterval(this._interval);
+
+  this._connected = false;
+
+  this._setStatus('aborted');
+
+  this.oDbg.log("Disconnected.",1);
+  this._handleEvent('ondisconnect');
+  this._handleEvent('onerror',
+                    JSJaCError('500','cancel','service-unavailable'));
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._checkInQ = function() {
+  for (var i=0; i<this._inQ.length && i<10; i++) {
+    var item = this._inQ[0];
+    this._inQ = this._inQ.slice(1,this._inQ.length);
+    var packet = JSJaCPacket.wrapNode(item);
+
+    if (!packet)
+      return;
+
+    this._handleEvent("packet_in", packet);
+
+    if (packet.pType && !this._handlePID(packet)) {
+      this._handleEvent(packet.pType()+'_in',packet);
+      this._handleEvent(packet.pType(),packet);
+    }
+  }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._checkQueue = function() {
+  if (this._pQueue.length != 0)
+    this._process();
+  return true;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doAuth = function() {
+  if (this.has_sasl && this.authtype == 'nonsasl')
+    this.oDbg.log("Warning: SASL present but not used", 1);
+
+  if (!this._doSASLAuth() &&
+      !this._doLegacyAuth()) {
+    this.oDbg.log("Auth failed for authtype "+this.authtype,1);
+    this.disconnect();
+    return false;
+  }
+  return true;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doInBandReg = function() {
+  if (this.authtype == 'saslanon' || this.authtype == 'anonymous')
+    return; // bullshit - no need to register if anonymous
+
+  /* ***
+   * In-Band Registration see JEP-0077
+   */
+
+  var iq = new JSJaCIQ();
+  iq.setType('set');
+  iq.setID('reg1');
+  iq.appendNode("query", {xmlns: "jabber:iq:register"},
+                [["username", this.username],
+                 ["password", this.pass]]);
+
+  this.send(iq,this._doInBandRegDone);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doInBandRegDone = function(iq) {
+  if (iq && iq.getType() == 'error') { // we failed to register
+    this.oDbg.log("registration failed for "+this.username,0);
+    this._handleEvent('onerror',iq.getChild('error'));
+    return;
+  }
+
+  this.oDbg.log(this.username + " registered succesfully",0);
+
+  this._doAuth();
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doLegacyAuth = function() {
+  if (this.authtype != 'nonsasl' && this.authtype != 'anonymous')
+    return false;
+
+  /* ***
+   * Non-SASL Authentication as described in JEP-0078
+   */
+  var iq = new JSJaCIQ();
+  iq.setIQ(null,'get','auth1');
+  iq.appendNode('query', {xmlns: 'jabber:iq:auth'},
+                [['username', this.username]]);
+
+  this.send(iq,this._doLegacyAuth2);
+  return true;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doLegacyAuth2 = function(iq) {
+  if (!iq || iq.getType() != 'result') {
+    if (iq && iq.getType() == 'error')
+      this._handleEvent('onerror',iq.getChild('error'));
+    this.disconnect();
+    return;
+  }
+
+  var use_digest = (iq.getChild('digest') != null);
+
+  /* ***
+   * Send authentication
+   */
+  var iq = new JSJaCIQ();
+  iq.setIQ(null,'set','auth2');
+
+  query = iq.appendNode('query', {xmlns: 'jabber:iq:auth'},
+                        [['username', this.username],
+                         ['resource', this.resource]]);
+
+  if (use_digest) { // digest login
+    query.appendChild(iq.buildNode('digest', {xmlns: 'jabber:iq:auth'},
+                                   hex_sha1(this.streamid + this.pass)));
+  } else if (this.allow_plain) { // use plaintext auth
+    query.appendChild(iq.buildNode('password', {xmlns: 'jabber:iq:auth'},
+                                   this.pass));
+  } else {
+    this.oDbg.log("no valid login mechanism found",1);
+    this.disconnect();
+    return false;
+  }
+
+  this.send(iq,this._doLegacyAuthDone);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doLegacyAuthDone = function(iq) {
+  if (iq.getType() != 'result') { // auth' failed
+    if (iq.getType() == 'error')
+      this._handleEvent('onerror',iq.getChild('error'));
+    this.disconnect();
+  } else
+    this._handleEvent('onconnect');
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doSASLAuth = function() {
+  if (this.authtype == 'nonsasl' || this.authtype == 'anonymous')
+    return false;
+
+  if (this.authtype == 'saslanon') {
+    if (this.mechs['ANONYMOUS']) {
+      this.oDbg.log("SASL using mechanism 'ANONYMOUS'",2);
+      return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>",
+                           this._doSASLAuthDone);
+    }
+    this.oDbg.log("SASL ANONYMOUS requested but not supported",1);
+  } else {
+    if (this.mechs['DIGEST-MD5']) {
+      this.oDbg.log("SASL using mechanism 'DIGEST-MD5'",2);
+      return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>",
+                           this._doSASLAuthDigestMd5S1);
+    } else if (this.allow_plain && this.mechs['PLAIN']) {
+      this.oDbg.log("SASL using mechanism 'PLAIN'",2);
+      var authStr = this.username+'@'+
+      this.domain+String.fromCharCode(0)+
+      this.username+String.fromCharCode(0)+
+      this.pass;
+      this.oDbg.log("authenticating with '"+authStr+"'",2);
+      authStr = b64encode(authStr);
+      return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>"+authStr+"</auth>",
+                           this._doSASLAuthDone);
+    }
+    this.oDbg.log("No SASL mechanism applied",1);
+    this.authtype = 'nonsasl'; // fallback
+  }
+  return false;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doSASLAuthDigestMd5S1 = function(el) {
+  if (el.nodeName != "challenge") {
+    this.oDbg.log("challenge missing",1);
+    this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));
+    this.disconnect();
+  } else {
+    var challenge = b64decode(el.firstChild.nodeValue);
+    this.oDbg.log("got challenge: "+challenge,2);
+    this._nonce = challenge.substring(challenge.indexOf("nonce=")+7);
+    this._nonce = this._nonce.substring(0,this._nonce.indexOf("\""));
+    this.oDbg.log("nonce: "+this._nonce,2);
+    if (this._nonce == '' || this._nonce.indexOf('\"') != -1) {
+      this.oDbg.log("nonce not valid, aborting",1);
+      this.disconnect();
+      return;
+    }
+
+    this._digest_uri = "xmpp/";
+    //     if (typeof(this.host) != 'undefined' && this.host != '') {
+    //       this._digest-uri += this.host;
+    //       if (typeof(this.port) != 'undefined' && this.port)
+    //         this._digest-uri += ":" + this.port;
+    //       this._digest-uri += '/';
+    //     }
+    this._digest_uri += this.domain;
+
+    this._cnonce = cnonce(14);
+
+    this._nc = '00000001';
+
+    var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+
+    ':'+this._nonce+':'+this._cnonce;
+
+    var A2 = 'AUTHENTICATE:'+this._digest_uri;
+
+    var response = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+
+                           this._cnonce+':auth:'+hex_md5(A2));
+
+    var rPlain = 'username="'+this.username+'",realm="'+this.domain+
+    '",nonce="'+this._nonce+'",cnonce="'+this._cnonce+'",nc="'+this._nc+
+    '",qop=auth,digest-uri="'+this._digest_uri+'",response="'+response+
+    '",charset="utf-8"';
+
+    this.oDbg.log("response: "+rPlain,2);
+
+    this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"+
+                  b64encode(rPlain)+"</response>",
+                  this._doSASLAuthDigestMd5S2);
+  }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doSASLAuthDigestMd5S2 = function(el) {
+  if (el.nodeName == 'failure') {
+    if (el.xml)
+      this.oDbg.log("auth error: "+el.xml,1);
+    else
+      this.oDbg.log("auth error",1);
+    this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));
+    this.disconnect();
+    return;
+  }
+
+  var response = b64decode(el.firstChild.nodeValue);
+  this.oDbg.log("response: "+response,2);
+
+  var rspauth = response.substring(response.indexOf("rspauth=")+8);
+  this.oDbg.log("rspauth: "+rspauth,2);
+
+  var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+
+  ':'+this._nonce+':'+this._cnonce;
+
+  var A2 = ':'+this._digest_uri;
+
+  var rsptest = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+
+                        this._cnonce+':auth:'+hex_md5(A2));
+  this.oDbg.log("rsptest: "+rsptest,2);
+
+  if (rsptest != rspauth) {
+    this.oDbg.log("SASL Digest-MD5: server repsonse with wrong rspauth",1);
+    this.disconnect();
+    return;
+  }
+
+    if (el.nodeName == 'success') {
+        this._reInitStream(JSJaC.bind(this._doStreamBind, this));
+    } else { // some extra turn
+        this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>",
+                      this._doSASLAuthDone);
+    }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doSASLAuthDone = function (el) {
+    if (el.nodeName != 'success') {
+        this.oDbg.log("auth failed",1);
+        this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));
+        this.disconnect();
+    } else {
+        this._reInitStream(JSJaC.bind(this._doStreamBind, this));
+    }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doStreamBind = function() {
+  var iq = new JSJaCIQ();
+  iq.setIQ(null,'set','bind_1');
+  iq.appendNode("bind", {xmlns: "urn:ietf:params:xml:ns:xmpp-bind"},
+                [["resource", this.resource]]);
+  this.oDbg.log(iq.xml());
+  this.send(iq,this._doXMPPSess);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doXMPPSess = function(iq) {
+  if (iq.getType() != 'result' || iq.getType() == 'error') { // failed
+    this.disconnect();
+    if (iq.getType() == 'error')
+      this._handleEvent('onerror',iq.getChild('error'));
+    return;
+  }
+
+  this.fulljid = iq.getChildVal("jid");
+  this.jid = this.fulljid.substring(0,this.fulljid.lastIndexOf('/'));
+
+  iq = new JSJaCIQ();
+  iq.setIQ(null,'set','sess_1');
+  iq.appendNode("session", {xmlns: "urn:ietf:params:xml:ns:xmpp-session"},
+                []);
+  this.oDbg.log(iq.xml());
+  this.send(iq,this._doXMPPSessDone);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._doXMPPSessDone = function(iq) {
+  if (iq.getType() != 'result' || iq.getType() == 'error') { // failed
+    this.disconnect();
+    if (iq.getType() == 'error')
+      this._handleEvent('onerror',iq.getChild('error'));
+    return;
+  } else
+    this._handleEvent('onconnect');
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._handleEvent = function(event,arg) {
+  event = event.toLowerCase(); // don't be case-sensitive here
+  this.oDbg.log("incoming event '"+event+"'",3);
+  if (!this._events[event])
+    return;
+  this.oDbg.log("handling event '"+event+"'",2);
+  for (var i=0;i<this._events[event].length; i++) {
+    var aEvent = this._events[event][i];
+    if (typeof aEvent.handler == 'function') {
+      try {
+        if (arg) {
+          if (arg.pType) { // it's a packet
+            if ((!arg.getNode().hasChildNodes() && aEvent.childName != '*') ||
+                               (arg.getNode().hasChildNodes() &&
+                                !arg.getChild(aEvent.childName, aEvent.childNS)))
+              continue;
+            if (aEvent.type != '*' &&
+                arg.getType() != aEvent.type)
+              continue;
+            this.oDbg.log(aEvent.childName+"/"+aEvent.childNS+"/"+aEvent.type+" => match for handler "+aEvent.handler,3);
+          }
+          if (aEvent.handler(arg)) {
+            // handled!
+            break;
+          }
+        }
+        else
+          if (aEvent.handler()) {
+            // handled!
+            break;
+          }
+      } catch (e) {
+
+        if (e.fileName&&e.lineNumber) {
+            this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+ e.message+' in '+e.fileName+' line '+e.lineNumber,1);
+        } else {
+            this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+ e.message,1);
+        }
+
+      }
+    }
+  }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._handlePID = function(aJSJaCPacket) {
+  if (!aJSJaCPacket.getID())
+    return false;
+  for (var i in this._regIDs) {
+    if (this._regIDs.hasOwnProperty(i) &&
+        this._regIDs[i] && i == aJSJaCPacket.getID()) {
+      var pID = aJSJaCPacket.getID();
+      this.oDbg.log("handling "+pID,3);
+      try {
+        if (this._regIDs[i].cb.call(this, aJSJaCPacket, this._regIDs[i].arg) === false) {
+          // don't unregister
+          return false;
+        } else {
+          this._unregisterPID(pID);
+          return true;
+        }
+      } catch (e) {
+        // broken handler?
+        this.oDbg.log(e.name+": "+ e.message, 1);
+        this._unregisterPID(pID);
+        return true;
+      }
+    }
+  }
+  return false;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._handleResponse = function(req) {
+  var rootEl = this._parseResponse(req);
+
+  if (!rootEl)
+    return;
+
+  for (var i=0; i<rootEl.childNodes.length; i++) {
+    if (this._sendRawCallbacks.length) {
+      var cb = this._sendRawCallbacks[0];
+      this._sendRawCallbacks = this._sendRawCallbacks.slice(1, this._sendRawCallbacks.length);
+      cb.fn.call(this, rootEl.childNodes.item(i), cb.arg);
+      continue;
+    }
+    this._inQ = this._inQ.concat(rootEl.childNodes.item(i));
+  }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
+    if (!doc) {
+        this.oDbg.log("nothing to parse ... aborting",1);
+        return false;
+    }
+
+    var errorTag;
+    if (doc.getElementsByTagNameNS) {
+        errorTag = doc.getElementsByTagNameNS("http://etherx.jabber.org/streams", "error").item(0);
+    } else {
+        var errors = doc.getElementsByTagName("error");
+        for (var i=0; i<errors.length; i++)
+            if (errors.item(i).namespaceURI == "http://etherx.jabber.org/streams" ||
+                errors.item(i).getAttribute('xmlns') == "http://etherx.jabber.org/streams") {
+                errorTag = errors.item(i);
+                break;
+            }
+    }
+
+    if (errorTag) {
+        this._setStatus("internal_server_error");
+        clearTimeout(this._timeout); // remove timer
+        clearInterval(this._interval);
+        clearInterval(this._inQto);
+        this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));
+        this._connected = false;
+        this.oDbg.log("Disconnected.",1);
+        this._handleEvent('ondisconnect');
+        return false;
+    }
+    
+    this.mechs = new Object();
+    var lMec1 = doc.getElementsByTagName("mechanisms");
+    this.has_sasl = false;
+    for (var i=0; i<lMec1.length; i++)
+        if (lMec1.item(i).getAttribute("xmlns") ==
+            "urn:ietf:params:xml:ns:xmpp-sasl") {
+            this.has_sasl=true;
+            var lMec2 = lMec1.item(i).getElementsByTagName("mechanism");
+            for (var j=0; j<lMec2.length; j++)
+                this.mechs[lMec2.item(j).firstChild.nodeValue] = true;
+            break;
+        }
+    if (this.has_sasl)
+        this.oDbg.log("SASL detected",2);
+    else {
+        this.oDbg.log("No support for SASL detected",2);
+        return false;
+    }
+    
+    // Get the server CAPS (if available)
+    this.server_caps=null;
+    var sCaps = doc.getElementsByTagName("c");
+    for (var i=0; i<sCaps.length; i++) {
+      var c_sCaps=sCaps.item(i);
+      var x_sCaps=c_sCaps.getAttribute("xmlns");
+      var v_sCaps=c_sCaps.getAttribute("ver");
+      
+      if ((x_sCaps == NS_CAPS) && v_sCaps) {
+        this.server_caps=v_sCaps;
+        break;
+      }
+    }
+    
+    return true;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._process = function(timerval) {
+  if (!this.connected()) {
+    this.oDbg.log("Connection lost ...",1);
+    if (this._interval)
+      clearInterval(this._interval);
+    return;
+  }
+
+  this.setPollInterval(timerval);
+
+  if (this._timeout)
+    clearTimeout(this._timeout);
+
+  var slot = this._getFreeSlot();
+
+  if (slot < 0)
+    return;
+
+  if (typeof(this._req[slot]) != 'undefined' &&
+      typeof(this._req[slot].r) != 'undefined' &&
+      this._req[slot].r.readyState != 4) {
+    this.oDbg.log("Slot "+slot+" is not ready");
+    return;
+  }
+
+  if (!this.isPolling() && this._pQueue.length == 0 &&
+      this._req[(slot+1)%2] && this._req[(slot+1)%2].r.readyState != 4) {
+    this.oDbg.log("all slots busy, standby ...", 2);
+    return;
+  }
+
+  if (!this.isPolling())
+    this.oDbg.log("Found working slot at "+slot,2);
+
+  this._req[slot] = this._setupRequest(true);
+
+  /* setup onload handler for async send */
+  this._req[slot].r.onreadystatechange =
+  JSJaC.bind(function() {
+               if (this._req[slot].r.readyState == 4) {
+                 this._setStatus('processing');
+                 this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);
+                 this._handleResponse(this._req[slot]);
+
+                 if (!this.connected())
+                   return;
+
+                 // schedule next tick
+                 if (this._pQueue.length) {
+                   this._timeout = setTimeout(JSJaC.bind(this._process, this),100);
+                 } else {
+                   this.oDbg.log("scheduling next poll in "+this.getPollInterval()+
+                                 " msec", 4);
+                   this._timeout = setTimeout(JSJaC.bind(this._process, this),this.getPollInterval());
+                 }
+               }
+             }, this);
+
+  try {
+    this._req[slot].r.onerror =
+      JSJaC.bind(function() {
+                   if (!this.connected())
+                     return;
+                   this._errcnt++;
+                   this.oDbg.log('XmlHttpRequest error ('+this._errcnt+')',1);
+                   if (this._errcnt > JSJAC_ERR_COUNT) {
+                     // abort
+                     this._abort();
+                     return false;
+                   }
+
+                   this._setStatus('onerror_fallback');
+
+                   // schedule next tick
+                   setTimeout(JSJaC.bind(this._resume, this),this.getPollInterval());
+                   return false;
+                 }, this);
+  } catch(e) { } // well ... no onerror property available, maybe we
+  // can catch the error somewhere else ...
+
+  var reqstr = this._getRequestString();
+
+  if (typeof(this._rid) != 'undefined') // remember request id if any
+    this._req[slot].rid = this._rid;
+
+  this.oDbg.log("sending: " + reqstr,4);
+  this._req[slot].r.send(reqstr);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._registerPID = function(pID,cb,arg) {
+  if (!pID || !cb)
+    return false;
+  this._regIDs[pID] = new Object();
+  this._regIDs[pID].cb = cb;
+  if (arg)
+    this._regIDs[pID].arg = arg;
+  this.oDbg.log("registered "+pID,3);
+  return true;
+};
+
+/**
+ * partial function binding sendEmpty to callback
+ * @private
+ */
+JSJaCConnection.prototype._prepSendEmpty = function(cb, ctx) {
+    return function() {
+        ctx._sendEmpty(JSJaC.bind(cb, ctx));
+    };
+};
+
+/**
+ * send empty request
+ * waiting for stream id to be able to proceed with authentication
+ * @private
+ */
+JSJaCConnection.prototype._sendEmpty = function(cb) {
+  var slot = this._getFreeSlot();
+  this._req[slot] = this._setupRequest(true);
+
+  this._req[slot].r.onreadystatechange =
+  JSJaC.bind(function() {
+               if (this._req[slot].r.readyState == 4) {
+                 this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);
+                   cb(this._req[slot].r); // handle response
+               }
+             },this);
+
+  if (typeof(this._req[slot].r.onerror) != 'undefined') {
+    this._req[slot].r.onerror =
+      JSJaC.bind(function(e) {
+                   this.oDbg.log('XmlHttpRequest error',1);
+                   return false;
+                 }, this);
+  }
+
+  var reqstr = this._getRequestString();
+  this.oDbg.log("sending: " + reqstr,4);
+  this._req[slot].r.send(reqstr);
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._sendRaw = function(xml,cb,arg) {
+  if (cb)
+    this._sendRawCallbacks.push({fn: cb, arg: arg});
+
+  this._pQueue.push(xml);
+  this._process();
+
+  return true;
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._setStatus = function(status) {
+  if (!status || status == '')
+    return;
+  if (status != this._status) { // status changed!
+    this._status = status;
+    this._handleEvent('onstatuschanged', status);
+    this._handleEvent('status_changed', status);
+  }
+};
+
+/**
+ * @private
+ */
+JSJaCConnection.prototype._unregisterPID = function(pID) {
+  if (!this._regIDs[pID])
+    return false;
+  this._regIDs[pID] = null;
+  this.oDbg.log("unregistered "+pID,3);
+  return true;
+};
+
+
+/**
+ * @fileoverview All stuff related to HTTP Binding
+ * @author Stefan Strigler steve@zeank.in-berlin.de
+ * @version $Revision$
+ */
+
+/**
+ * Instantiates an HTTP Binding session
+ * @class Implementation of {@link
+ * http://www.xmpp.org/extensions/xep-0206.html XMPP Over BOSH}
+ * formerly known as HTTP Binding.
+ * @extends JSJaCConnection
+ * @constructor
+ */
+function JSJaCHttpBindingConnection(oArg) {
+  /**
+   * @ignore
+   */
+  this.base = JSJaCConnection;
+  this.base(oArg);
+
+  // member vars
+  /**
+   * @private
+   */
+  this._hold = JSJACHBC_MAX_HOLD;
+  /**
+   * @private
+   */
+  this._inactivity = 0;
+  /**
+   * @private
+   */
+  this._last_requests = new Object(); // 'hash' storing hold+1 last requests
+  /**
+   * @private
+   */
+  this._last_rid = 0;                 // I know what you did last summer
+  /**
+   * @private
+   */
+  this._min_polling = 0;
+
+  /**
+   * @private
+   */
+  this._pause = 0;
+  /**
+   * @private
+   */
+  this._wait = JSJACHBC_MAX_WAIT;
+}
+JSJaCHttpBindingConnection.prototype = new JSJaCConnection();
+
+/**
+ * Inherit an instantiated HTTP Binding session
+ */
+JSJaCHttpBindingConnection.prototype.inherit = function(oArg) {
+  if (oArg.jid) {
+    var oJid = new JSJaCJID(oArg.jid);
+    this.domain = oJid.getDomain();
+    this.username = oJid.getNode();
+    this.resource = oJid.getResource();
+  } else {
+    this.domain = oArg.domain || 'localhost';
+    this.username = oArg.username;
+    this.resource = oArg.resource;
+  }
+  this._sid = oArg.sid;
+  this._rid = oArg.rid;
+  this._min_polling = oArg.polling;
+  this._inactivity = oArg.inactivity;
+  this._setHold(oArg.requests-1);
+  this.setPollInterval(this._timerval);
+  if (oArg.wait)
+    this._wait = oArg.wait; // for whatever reason
+
+  this._connected = true;
+
+  this._handleEvent('onconnect');
+
+  this._interval= setInterval(JSJaC.bind(this._checkQueue, this),
+                              JSJAC_CHECKQUEUEINTERVAL);
+  this._inQto = setInterval(JSJaC.bind(this._checkInQ, this),
+                            JSJAC_CHECKINQUEUEINTERVAL);
+  this._timeout = setTimeout(JSJaC.bind(this._process, this),
+                             this.getPollInterval());
+};
+
+/**
+ * Sets poll interval
+ * @param {int} timerval the interval in seconds
+ */
+JSJaCHttpBindingConnection.prototype.setPollInterval = function(timerval) {
+  if (timerval && !isNaN(timerval)) {
+    if (!this.isPolling())
+      this._timerval = 100;
+    else if (this._min_polling && timerval < this._min_polling*1000)
+      this._timerval = this._min_polling*1000;
+    else if (this._inactivity && timerval > this._inactivity*1000)
+      this._timerval = this._inactivity*1000;
+    else
+      this._timerval = timerval;
+  }
+  return this._timerval;
+};
+
+/**
+ * whether this session is in polling mode
+ * @type boolean
+ */
+JSJaCHttpBindingConnection.prototype.isPolling = function() { return (this._hold == 0) };
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getFreeSlot = function() {
+  for (var i=0; i<this._hold+1; i++)
+    if (typeof(this._req[i]) == 'undefined' || typeof(this._req[i].r) == 'undefined' || this._req[i].r.readyState == 4)
+      return i;
+  return -1; // nothing found
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getHold = function() { return this._hold; };
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getRequestString = function(raw, last) {
+  raw = raw || '';
+  var reqstr = '';
+
+  // check if we're repeating a request
+
+  if (this._rid <= this._last_rid && typeof(this._last_requests[this._rid]) != 'undefined') // repeat!
+    reqstr = this._last_requests[this._rid].xml;
+  else { // grab from queue
+    var xml = '';
+    while (this._pQueue.length) {
+      var curNode = this._pQueue[0];
+      xml += curNode;
+      this._pQueue = this._pQueue.slice(1,this._pQueue.length);
+    }
+
+    reqstr = "<body xml:lang='"+XML_LANG+"' rid='"+this._rid+"' sid='"+this._sid+"' xmlns='http://jabber.org/protocol/httpbind' ";
+    if (JSJAC_HAVEKEYS) {
+      reqstr += "key='"+this._keys.getKey()+"' ";
+      if (this._keys.lastKey()) {
+        this._keys = new JSJaCKeys(hex_sha1,this.oDbg);
+        reqstr += "newkey='"+this._keys.getKey()+"' ";
+      }
+    }
+    if (last)
+      reqstr += "type='terminate'";
+    else if (this._reinit) {
+      if (JSJACHBC_USE_BOSH_VER)
+        reqstr += "xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh' to='"+this.domain+"'";
+      this._reinit = false;
+    }
+
+    if (xml != '' || raw != '') {
+      reqstr += ">" + raw + xml + "</body>";
+    } else {
+      reqstr += "/>";
+    }
+
+    this._last_requests[this._rid] = new Object();
+    this._last_requests[this._rid].xml = reqstr;
+    this._last_rid = this._rid;
+
+    for (var i in this._last_requests)
+      if (this._last_requests.hasOwnProperty(i) &&
+          i < this._rid-this._hold)
+        delete(this._last_requests[i]); // truncate
+  }
+
+  return reqstr;
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getInitialRequestString = function() {
+  var reqstr = "<body xml:lang='"+XML_LANG+"' content='text/xml; charset=utf-8' hold='"+this._hold+"' xmlns='http://jabber.org/protocol/httpbind' to='"+this.authhost+"' wait='"+this._wait+"' rid='"+this._rid+"'";
+  if (this.secure)
+    reqstr += " secure='"+this.secure+"'";
+  if (JSJAC_HAVEKEYS) {
+    this._keys = new JSJaCKeys(hex_sha1,this.oDbg); // generate first set of keys
+    key = this._keys.getKey();
+    reqstr += " newkey='"+key+"'";
+  }
+
+  if (JSJACHBC_USE_BOSH_VER) {
+    reqstr += " ver='" + JSJACHBC_BOSH_VERSION + "'";
+    reqstr += " xmlns:xmpp='urn:xmpp:xbosh'";
+    if (this.authtype == 'sasl' || this.authtype == 'saslanon')
+      reqstr += " xmpp:version='1.0'";
+  }
+  reqstr += "/>";
+  return reqstr;
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getStreamID = function(req) {
+
+  this.oDbg.log(req.responseText,4);
+
+  if (!req.responseXML || !req.responseXML.documentElement) {
+    this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
+    return;
+  }
+  var body = req.responseXML.documentElement;
+  
+  // any session error?
+  if(body.getAttribute('type') == 'terminate') {
+    this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
+    return;
+  }
+  
+  // extract stream id used for non-SASL authentication
+  if (body.getAttribute('authid')) {
+    this.streamid = body.getAttribute('authid');
+    this.oDbg.log("got streamid: "+this.streamid,2);
+  }
+
+  if (!this._parseStreamFeatures(body)) {
+      this._sendEmpty(JSJaC.bind(this._getStreamID, this));
+      return;
+  }
+
+  this._timeout = setTimeout(JSJaC.bind(this._process, this),
+                             this.getPollInterval());
+
+  if (this.register)
+    this._doInBandReg();
+  else
+    this._doAuth();
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._getSuspendVars = function() {
+  return ('host,port,secure,_rid,_last_rid,_wait,_min_polling,_inactivity,_hold,_last_requests,_pause').split(',');
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._handleInitialResponse = function(req) {
+  try {
+    // This will throw an error on Mozilla when the connection was refused
+    this.oDbg.log(req.getAllResponseHeaders(),4);
+    this.oDbg.log(req.responseText,4);
+  } catch(ex) {
+    this.oDbg.log("No response",4);
+  }
+
+  if (req.status != 200 || !req.responseXML) {
+    this.oDbg.log("initial response broken (status: "+req.status+")",1);
+    this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
+    return;
+  }
+  var body = req.responseXML.documentElement;
+
+  if (!body || body.tagName != 'body' || body.namespaceURI != 'http://jabber.org/protocol/httpbind') {
+    this.oDbg.log("no body element or incorrect body in initial response",1);
+    this._handleEvent("onerror",JSJaCError("500","wait","internal-service-error"));
+    return;
+  }
+
+  // Check for errors from the server
+  if (body.getAttribute("type") == "terminate") {
+    this.oDbg.log("invalid response:\n" + req.responseText,1);
+    clearTimeout(this._timeout); // remove timer
+    this._connected = false;
+    this.oDbg.log("Disconnected.",1);
+    this._handleEvent('ondisconnect');
+    this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
+    return;
+  }
+
+  // get session ID
+  this._sid = body.getAttribute('sid');
+  this.oDbg.log("got sid: "+this._sid,2);
+
+  // get attributes from response body
+  if (body.getAttribute('polling'))
+    this._min_polling = body.getAttribute('polling');
+
+  if (body.getAttribute('inactivity'))
+    this._inactivity = body.getAttribute('inactivity');
+
+  if (body.getAttribute('requests'))
+    this._setHold(body.getAttribute('requests')-1);
+  this.oDbg.log("set hold to " + this._getHold(),2);
+
+  if (body.getAttribute('ver'))
+    this._bosh_version = body.getAttribute('ver');
+
+  if (body.getAttribute('maxpause'))
+    this._pause = Number.min(body.getAttribute('maxpause'), JSJACHBC_MAXPAUSE);
+
+  // must be done after response attributes have been collected
+  this.setPollInterval(this._timerval);
+
+  /* start sending from queue for not polling connections */
+  this._connected = true;
+
+  this._inQto = setInterval(JSJaC.bind(this._checkInQ, this),
+                            JSJAC_CHECKINQUEUEINTERVAL);
+  this._interval= setInterval(JSJaC.bind(this._checkQueue, this),
+                              JSJAC_CHECKQUEUEINTERVAL);
+
+  /* wait for initial stream response to extract streamid needed
+   * for digest auth
+   */
+  this._getStreamID(req);
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._parseResponse = function(req) {
+  if (!this.connected() || !req)
+    return null;
+
+  var r = req.r; // the XmlHttpRequest
+
+  try {
+    if (r.status == 404 || r.status == 403) {
+      // connection manager killed session
+      this._abort();
+      return null;
+    }
+
+    if (r.status != 200 || !r.responseXML) {
+      this._errcnt++;
+      var errmsg = "invalid response ("+r.status+"):\n" + r.getAllResponseHeaders()+"\n"+r.responseText;
+      if (!r.responseXML)
+        errmsg += "\nResponse failed to parse!";
+      this.oDbg.log(errmsg,1);
+      if (this._errcnt > JSJAC_ERR_COUNT) {
+        // abort
+        this._abort();
+        return null;
+      }
+
+      if (this.connected()) {
+        this.oDbg.log("repeating ("+this._errcnt+")",1);
+        this._setStatus('proto_error_fallback');
+
+        // schedule next tick
+        setTimeout(JSJaC.bind(this._resume, this),
+                   this.getPollInterval());
+      }
+
+      return null;
+    }
+  } catch (e) {
+    this.oDbg.log("XMLHttpRequest error: status not available", 1);
+         this._errcnt++;
+         if (this._errcnt > JSJAC_ERR_COUNT) {
+           // abort
+           this._abort();
+         } else {
+      if (this.connected()) {
+             this.oDbg.log("repeating ("+this._errcnt+")",1);
+
+             this._setStatus('proto_error_fallback');
+
+             // schedule next tick
+             setTimeout(JSJaC.bind(this._resume, this),
+                   this.getPollInterval());
+      }
+    }
+    return null;
+  }
+
+  var body = r.responseXML.documentElement;
+  if (!body || body.tagName != 'body' ||
+         body.namespaceURI != 'http://jabber.org/protocol/httpbind') {
+    this.oDbg.log("invalid response:\n" + r.responseText,1);
+
+    clearTimeout(this._timeout); // remove timer
+    clearInterval(this._interval);
+    clearInterval(this._inQto);
+
+    this._connected = false;
+    this.oDbg.log("Disconnected.",1);
+    this._handleEvent('ondisconnect');
+
+    this._setStatus('internal_server_error');
+    this._handleEvent('onerror',
+                     JSJaCError('500','wait','internal-server-error'));
+
+    return null;
+  }
+
+  if (typeof(req.rid) != 'undefined' && this._last_requests[req.rid]) {
+    if (this._last_requests[req.rid].handled) {
+      this.oDbg.log("already handled "+req.rid,2);
+      return null;
+    } else
+      this._last_requests[req.rid].handled = true;
+  }
+
+
+  // Check for errors from the server
+  if (body.getAttribute("type") == "terminate") {
+    // read condition
+    var condition = body.getAttribute('condition');
+
+    if (condition != "item-not-found") {
+      this.oDbg.log("session terminated:\n" + r.responseText,1);
+
+      clearTimeout(this._timeout); // remove timer
+      clearInterval(this._interval);
+      clearInterval(this._inQto);
+
+      try {
+        removeDB('jsjac', 'state');
+      } catch (e) {}
+
+      this._connected = false;
+
+      if (condition == "remote-stream-error")
+        if (body.getElementsByTagName("conflict").length > 0)
+          this._setStatus("session-terminate-conflict");
+      if (condition == null)
+        condition = 'session-terminate';
+      this._handleEvent('onerror',JSJaCError('503','cancel',condition));
+
+      this.oDbg.log("Aborting remaining connections",4);
+
+      for (var i=0; i<this._hold+1; i++) {
+        try {
+          this._req[i].r.abort();
+        } catch(e) { this.oDbg.log(e, 1); }
+      }
+
+      this.oDbg.log("parseResponse done with terminating", 3);
+
+      this.oDbg.log("Disconnected.",1);
+      this._handleEvent('ondisconnect');
+    } else {
+      this._errcnt++;
+      if (this._errcnt > JSJAC_ERR_COUNT)
+        this._abort();
+    }
+    return null;
+  }
+
+  // no error
+  this._errcnt = 0;
+  return r.responseXML.documentElement;
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._reInitStream = function(cb) {
+    // tell http binding to reinit stream with/before next request
+    this._reinit = true;
+
+    this._sendEmpty(this._prepReInitStreamWait(cb));
+};
+
+
+JSJaCHttpBindingConnection.prototype._prepReInitStreamWait = function(cb) {
+    return JSJaC.bind(function(req) {
+        this._reInitStreamWait(req, cb);
+    }, this);
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
+    this.oDbg.log("checking for stream features");
+    var doc = req.responseXML.documentElement;
+    this.oDbg.log(doc);
+    if (doc.getElementsByTagNameNS) {
+        this.oDbg.log("checking with namespace");
+        var features = doc.getElementsByTagNameNS('http://etherx.jabber.org/streams',
+                                                'features').item(0);
+        if (features) {
+            var bind = features.getElementsByTagNameNS('urn:ietf:params:xml:ns:xmpp-bind',
+                                                       'bind').item(0);
+        }
+    } else {
+        var featuresNL = doc.getElementsByTagName('stream:features');
+        for (var i=0, l=featuresNL.length; i<l; i++) {
+            if (featuresNL.item(i).namespaceURI == 'http://etherx.jabber.org/streams' ||
+                featuresNL.item(i).getAttribute('xmlns') == 
+                'http://etherx.jabber.org/streams') {
+                var features = featuresNL.item(i);
+                break;
+            }
+        }
+        if (features) {
+            var bind = features.getElementsByTagName('bind');
+            for (var i=0, l=bind.length; i<l; i++) {
+                if (bind.item(i).namespaceURI == 'urn:ietf:params:xml:ns:xmpp-bind' ||
+                    bind.item(i).getAttribute('xmlns') == 
+                    'urn:ietf:params:xml:ns:xmpp-bind') {
+                    bind = bind.item(i);
+                    break;
+                }
+            }
+        }
+    }
+    this.oDbg.log(features);
+    this.oDbg.log(bind);
+    
+    if (features) {
+        if (bind) {
+            cb();
+        } else {
+            this.oDbg.log("no bind feature - giving up",1);
+            this._handleEvent('onerror',JSJaCError('503','cancel',"service-unavailable"));
+            this._connected = false;
+            this.oDbg.log("Disconnected.",1);
+            this._handleEvent('ondisconnect');
+        }
+    } else {
+        // wait
+        this._sendEmpty(this._prepReInitStreamWait(cb));
+    }
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._resume = function() {
+  /* make sure to repeat last request as we can be sure that
+   * it had failed (only if we're not using the 'pause' attribute
+   */
+  if (this._pause == 0 && this._rid >= this._last_rid)
+    this._rid = this._last_rid-1;
+
+  this._process();
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._setHold = function(hold)  {
+  if (!hold || isNaN(hold) || hold < 0)
+    hold = 0;
+  else if (hold > JSJACHBC_MAX_HOLD)
+    hold = JSJACHBC_MAX_HOLD;
+  this._hold = hold;
+  return this._hold;
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._setupRequest = function(async) {
+  var req = new Object();
+  var r = XmlHttp.create();
+  try {
+    r.open("POST",this._httpbase,async);
+    r.setRequestHeader('Content-Type','text/xml; charset=utf-8');
+  } catch(e) { this.oDbg.log(e,1); }
+  req.r = r;
+  this._rid++;
+  req.rid = this._rid;
+  return req;
+};
+
+/**
+ * @private
+ */
+JSJaCHttpBindingConnection.prototype._suspend = function() {
+  if (this._pause == 0)
+    return; // got nothing to do
+
+  var slot = this._getFreeSlot();
+  // Intentionally synchronous
+  this._req[slot] = this._setupRequest(false);
+
+  var reqstr = "<body xml:lang='"+XML_LANG+"' pause='"+this._pause+"' xmlns='http://jabber.org/protocol/httpbind' sid='"+this._sid+"' rid='"+this._rid+"'";
+  if (JSJAC_HAVEKEYS) {
+    reqstr += " key='"+this._keys.getKey()+"'";
+    if (this._keys.lastKey()) {
+      this._keys = new JSJaCKeys(hex_sha1,this.oDbg);
+      reqstr += " newkey='"+this._keys.getKey()+"'";
+    }
+
+  }
+  reqstr += ">";
+
+  while (this._pQueue.length) {
+    var curNode = this._pQueue[0];
+    reqstr += curNode;
+    this._pQueue = this._pQueue.slice(1,this._pQueue.length);
+  }
+
+  //reqstr += "<presence type='unavailable' xmlns='jabber:client'/>";
+  reqstr += "</body>";
+
+  this.oDbg.log("Disconnecting: " + reqstr,4);
+  this._req[slot].r.send(reqstr);
+};
diff --git a/jappixmini/jappix/js/jxhr.js b/jappixmini/jappix/js/jxhr.js
new file mode 100644 (file)
index 0000000..deaf511
--- /dev/null
@@ -0,0 +1,116 @@
+// jXHR.js (JSON-P XHR)\r
+// v0.1 (c) Kyle Simpson\r
+// MIT License\r
+// modified by gueron Jonathan to work with strophe lib\r
+// for http://www.iadvize.com\r
+\r
+(function(global){\r
+       var SETTIMEOUT = global.setTimeout, // for better compression\r
+               doc = global.document,\r
+               callback_counter = 0;\r
+               \r
+       global.jXHR = function() {\r
+               var script_url,\r
+                       script_loaded,\r
+                       jsonp_callback,\r
+                       scriptElem,\r
+                       publicAPI = null;\r
+                       \r
+               function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }\r
+                       \r
+               function reset() {\r
+                       script_loaded = false;\r
+                       script_url = "";\r
+                       removeScript();\r
+                       scriptElem = null;\r
+                       fireReadyStateChange(0);\r
+               }\r
+               \r
+               function ThrowError(msg) {\r
+                       try { \r
+                               publicAPI.onerror.call(publicAPI,msg,script_url); \r
+                       } catch (err) { \r
+                               //throw new Error(msg); \r
+                       }\r
+               }\r
+\r
+               function handleScriptLoad() {\r
+                       if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }\r
+                       this.onload = this.onreadystatechange = null; // prevent memory leak\r
+                       script_loaded = true;\r
+                       if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");\r
+                       removeScript();\r
+               }\r
+               \r
+               function parseXMLString(xmlStr) {\r
+                       var xmlDoc = null;\r
+                       if(window.DOMParser) {\r
+                               var parser = new DOMParser();\r
+                               xmlDoc = parser.parseFromString(xmlStr,"text/xml");\r
+                       }\r
+                       else {\r
+                               xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); \r
+                               xmlDoc.async="false";\r
+                               xmlDoc.loadXML(xmlStr);\r
+                       }\r
+                       return xmlDoc;\r
+               }\r
+               \r
+               function fireReadyStateChange(rs,args) {\r
+               \r
+                       args = args || [];\r
+                       publicAPI.readyState = rs;\r
+                       if (rs == 4) {\r
+                               publicAPI.responseText = args[0].reply;\r
+                               publicAPI.responseXML = parseXMLString(args[0].reply);\r
+                       }\r
+                       if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);\r
+               }\r
+                               \r
+               publicAPI = {\r
+                       onerror:null,\r
+                       onreadystatechange:null,\r
+                       readyState:0,\r
+                       status:200,\r
+                       responseBody: null,\r
+                       responseText: null,\r
+                       responseXML: null,\r
+                       open:function(method,url){\r
+                               reset();\r
+                               var internal_callback = "cb"+(callback_counter++);\r
+                               (function(icb){\r
+                                       global.jXHR[icb] = function() {\r
+                                               try { fireReadyStateChange.call(publicAPI,4,arguments); } \r
+                                               catch(err) { \r
+                                                       publicAPI.readyState = -1;\r
+                                                       ThrowError("Script failed to run ["+script_url+"]."); \r
+                                               }\r
+                                               global.jXHR[icb] = null;\r
+                                       };\r
+                               })(internal_callback);\r
+                               script_url = url + '?callback=?jXHR&data=';\r
+                               script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);\r
+                               fireReadyStateChange(1);\r
+                       },\r
+                       send:function(data){\r
+                               script_url = script_url + encodeURIComponent(data);\r
+                               SETTIMEOUT(function(){\r
+                                       scriptElem = doc.createElement("script");\r
+                                       scriptElem.setAttribute("type","text/javascript");\r
+                                       scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};\r
+                                       scriptElem.setAttribute("src",script_url);\r
+                                       doc.getElementsByTagName("head")[0].appendChild(scriptElem);\r
+                               },0);\r
+                               fireReadyStateChange(2);\r
+                       },\r
+                       abort:function(){},\r
+                       setRequestHeader:function(){}, // noop\r
+                       getResponseHeader:function(){return "";}, // basically noop\r
+                       getAllResponseHeaders:function(){return [];} // ditto\r
+               };\r
+\r
+               reset();\r
+               \r
+               return publicAPI;\r
+       };\r
+})(window);\r
diff --git a/jappixmini/jappix/js/links.js b/jappixmini/jappix/js/links.js
new file mode 100644 (file)
index 0000000..d0e4339
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+
+Jappix - An open social platform
+These are the links JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Maranda
+Last revision: 26/08/11
+
+*/
+
+// Apply links in a string
+function applyLinks(string, mode, style) {
+       // Special stuffs
+       var style, target;
+       
+       // Links style
+       if(!style)
+               style = '';
+       else
+               style = ' style="' + style + '"';
+       
+       // Open in new tabs
+       if(mode != 'xhtml-im')
+               target = ' target="_blank"';
+       else
+               target = '';
+       
+       // XMPP address
+       string = string.replace(/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi, '$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5');
+       
+       // Simple link
+       string = string.replace(/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1<a href="$2"' + target + style + '>$2</a>');
+       
+       return string;
+}
diff --git a/jappixmini/jappix/js/me.js b/jappixmini/jappix/js/me.js
new file mode 100644 (file)
index 0000000..5720df3
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+
+Jappix - An open social platform
+These are the Jappix Me tool functions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+// Opens the Me tools
+function openMe() {    
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Public profile") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<a class="me-images logo" href="https://me.jappix.com/" target="_blank"></a>' + 
+               
+               '<div class="infos">' + 
+                       '<p class="infos-title">' + _e("Your profile anywhere on the Web.") + '</p>' + 
+                       '<p>' + printf(_e("%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."), '<a href="https://me.jappix.com/" target="_blank">Jappix Me</a>') + '</p>' + 
+                       '<p>' + _e("Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year.") + '</p>' + 
+                       '<p>' + _e("You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!") + '</p>' + 
+               '</div>' + 
+               
+               '<a class="go one-button" href="https://me.jappix.com/new" target="_blank">' + _e("Yay, let's create my public profile!") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('me', html);
+       
+       // Associate the events
+       launchMe();
+       
+       logThis('Public profile tool opened.');
+}
+
+// Closes the Me tools
+function closeMe() {
+       // Destroy the popup
+       destroyPopup('me');
+       
+       return false;
+}
+
+// Plugin launcher
+function launchMe() {
+       // Click events
+       $('#me .content a.go').click(function() {
+               closeMe();
+       });
+       
+       $('#me .bottom .finish').click(closeMe);
+}
\ No newline at end of file
diff --git a/jappixmini/jappix/js/message.js b/jappixmini/jappix/js/message.js
new file mode 100644 (file)
index 0000000..0b7eaeb
--- /dev/null
@@ -0,0 +1,900 @@
+/*
+
+Jappix - An open social platform
+These are the messages JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Maranda
+Last revision: 01/09/11
+
+*/
+
+// Handles the incoming message packets
+function handleMessage(message) {
+       // Error packet? Stop!
+       if(handleErrorReply(message))
+               return;
+       
+       // We get the message items
+       var from = fullXID(getStanzaFrom(message));
+       var id = message.getID();
+       var type = message.getType();
+       var body = trim(message.getBody());
+       var node = message.getNode();
+       var subject = trim(message.getSubject());
+       
+       // We generate some values
+       var xid = bareXID(from);
+       var resource = thisResource(from);
+       var hash = hex_md5(xid);
+       var xHTML = $(node).find('html body').size();
+       var GCUser = false;
+       
+       // This message comes from a groupchat user
+       if(isPrivate(xid) && ((type == 'chat') || !type) && resource) {
+               GCUser = true;
+               xid = from;
+               hash = hex_md5(xid);
+       }
+       
+       // Get message date
+       var time, stamp, d_stamp;
+       
+       // Read the delay
+       var delay = readMessageDelay(node);
+       
+       // Any delay?
+       if(delay) {
+               time = relativeDate(delay);
+               d_stamp = Date.jab2date(delay);
+       }
+       
+       // No delay: get actual time
+       else {
+               time = getCompleteTime();
+               d_stamp = new Date();
+       }
+       
+       // Get the date stamp
+       stamp = extractStamp(d_stamp);
+       
+       // Received message
+       if(hasReceived(message))
+               return messageReceived(hash, id);
+       
+       // Chatstate message
+       if(node && !delay && ((((type == 'chat') || !type) && !exists('#page-switch .' + hash + ' .unavailable')) || (type == 'groupchat'))) {
+               /* REF: http://xmpp.org/extensions/xep-0085.html */
+               
+               // Re-process the hash
+               var chatstate_hash = hash;
+               
+               if(type == 'groupchat')
+                       chatstate_hash = hex_md5(from);
+               
+               // Do something depending of the received state
+               if($(node).find('active').size()) {
+                       displayChatState('active', chatstate_hash, type);
+                       
+                       // Tell Jappix the entity supports chatstates
+                       $('#' + chatstate_hash + ' .message-area').attr('data-chatstates', 'true');
+                       
+                       logThis('Active chatstate received from: ' + from);
+               }
+               
+               else if($(node).find('composing').size())
+                       displayChatState('composing', chatstate_hash, type);
+               
+               else if($(node).find('paused').size())
+                       displayChatState('paused', chatstate_hash, type);
+               
+               else if($(node).find('inactive').size())
+                       displayChatState('inactive', chatstate_hash, type);
+               
+               else if($(node).find('gone').size())
+                       displayChatState('gone', chatstate_hash, type);
+       }
+       
+       // Invite message
+       if($(node).find('x[xmlns=' + NS_MUC_USER + '] invite').size()) {
+               // We get the needed values
+               var iFrom = $(node).find('x[xmlns=' + NS_MUC_USER + '] invite').attr('from');
+               var iRoom = $(node).find('x[xmlns=' + NS_XCONFERENCE + ']').attr('jid');
+               
+               // Old invite method?
+               if(!iRoom)
+                       iRoom = from;
+               
+               // We display the notification
+               newNotification('invite_room', iFrom, [iRoom], body);
+               
+               logThis('Invite Request from: ' + iFrom + ' to join: ' + iRoom);
+               
+               return false;
+       }
+       
+       // Request message
+       if(message.getChild('confirm', NS_HTTP_AUTH)) {
+               // Open a new notification
+               newNotification('request', xid, [message], body);
+               
+               logThis('HTTP Request from: ' + xid);
+               
+               return false;
+       }
+       
+       // OOB message
+       if(message.getChild('x', NS_XOOB)) {
+               handleOOB(from, id, 'x', node);
+               
+               logThis('Message OOB request from: ' + xid);
+               
+               return false;
+       }
+       
+       // Roster Item Exchange message
+       if(message.getChild('x', NS_ROSTERX)) {
+               // Open a new notification
+               newNotification('rosterx', xid, [message], body);
+               
+               logThis('Roster Item Exchange from: ' + xid);
+               
+               return false;
+       }
+       
+       // Normal message
+       if((type == 'normal') && body) {
+               // Message date
+               var messageDate = delay;
+               
+               // No message date?
+               if(!messageDate)
+                       messageDate = getXMPPTime('utc');
+               
+               // Message ID
+               var messageID = hex_md5(xid + subject + messageDate);
+               
+               // We store the received message
+               storeInboxMessage(xid, subject, body, 'unread', messageID, messageDate);
+               
+               // Display the inbox message
+               if(exists('#inbox'))
+                       displayInboxMessage(xid, subject, body, 'unread', messageID, messageDate);
+               
+               // Check we have new messages (play a sound if any unread messages)
+               if(checkInboxMessages())
+                       soundPlay(2);
+               
+               // Send it to the server
+               storeInbox();
+               
+               return false;
+       }
+       
+       // PubSub event
+       if($(node).find('event').attr('xmlns') == NS_PUBSUB_EVENT) {
+               // We get the needed values
+               var iParse = $(node).find('event items');
+               var iNode = iParse.attr('node');
+               
+               // Turn around the different result cases
+               if(iNode) {
+                       switch(iNode) {
+                               // Mood
+                               case NS_MOOD:
+                                       // Retrieve the values
+                                       var iMood = iParse.find('mood');
+                                       var fValue = '';
+                                       var tText = '';
+                                       
+                                       // There's something
+                                       if(iMood.children().size()) {
+                                               // Read the value
+                                               fValue = node.getElementsByTagName('mood').item(0).childNodes.item(0).nodeName;
+                                               
+                                               // Read the text
+                                               tText = iMood.find('text').text();
+                                               
+                                               // Avoid errors
+                                               if(!fValue)
+                                                       fValue = '';
+                                       }
+                                       
+                                       // Store the PEP event (and display it)
+                                       storePEP(xid, 'mood', fValue, tText);
+                                       
+                                       break;
+                               
+                               // Activity
+                               case NS_ACTIVITY:
+                                       // Retrieve the values
+                                       var iActivity = iParse.find('activity');
+                                       var sValue = '';
+                                       var tText = '';
+                                       
+                                       // There's something
+                                       if(iActivity.children().size()) {
+                                               // Read the value
+                                               fValue = node.getElementsByTagName('activity').item(0).childNodes.item(0).nodeName;
+                                               
+                                               // Read the text
+                                               tText = iActivity.find('text').text();
+                                               
+                                               // Avoid errors
+                                               if(!fValue)
+                                                       fValue = '';
+                                       }
+                                       
+                                       // Store the PEP event (and display it)
+                                       storePEP(xid, 'activity', fValue, tText);
+                                       
+                                       break;
+                               
+                               // Tune
+                               case NS_TUNE:
+                                       // Retrieve the values
+                                       var iTune = iParse.find('tune');
+                                       var tArtist = iTune.find('artist').text();
+                                       var tSource = iTune.find('source').text();
+                                       var tTitle = iTune.find('title').text();
+                                       var tURI = iTune.find('uri').text();
+                                       
+                                       // Store the PEP event (and display it)
+                                       storePEP(xid, 'tune', tArtist, tTitle, tSource, tURI);
+                                       
+                                       break;
+                               
+                               // Geolocation
+                               case NS_GEOLOC:
+                                       // Retrieve the values
+                                       var iGeoloc = iParse.find('geoloc');
+                                       var tLat = iGeoloc.find('lat').text();
+                                       var tLon = iGeoloc.find('lon').text();
+                                       
+                                       // Any extra-values?
+                                       var tLocality = iGeoloc.find('locality').text();
+                                       var tRegion = iGeoloc.find('region').text();
+                                       var tCountry = iGeoloc.find('country').text();
+                                       var tHuman = humanPosition(tLocality, tRegion, tCountry);
+                                       
+                                       // Store the PEP event (and display it)
+                                       storePEP(xid, 'geoloc', tLat, tLon, tHuman);
+                                       
+                                       break;
+                               
+                               // Microblog
+                               case NS_URN_MBLOG:
+                                       displayMicroblog(message, xid, hash, 'mixed', 'push');
+                                       
+                                       break;
+                               
+                               // Inbox
+                               case NS_URN_INBOX:
+                                       // Do not handle friend's notifications
+                                       if(xid == getXID())
+                                               handleNotifications(message);
+                                       
+                                       break;
+                       }
+               }
+               
+               return false;
+       }
+       
+       // If this is a room topic message
+       if(subject && (type == 'groupchat')) {
+               // Filter the vars
+               var filter_subject = subject.replace(/\n+/g, ' ');
+               var filteredSubject = filterThisMessage(filter_subject, resource, true);
+               var filteredName = resource.htmlEnc();
+               
+               // Display the new subject at the top
+               $('#' + hash + ' .top .name .bc-infos .muc-topic').replaceWith('<span class="muc-topic" title="' + filter_subject + '">' + filteredSubject + '</span>');
+               
+               // Display the new subject as a system message
+               if(resource) {
+                       var topic_body = filteredName + ' ' + _e("changed the subject to:") + ' ' + filterThisMessage(subject, resource, true);
+                       displayMessage(type, from, hash, filteredName, topic_body, time, stamp, 'system-message', false);
+               }
+       }
+       
+       // If the message has a content
+       if(xHTML || body) {
+               var filteredMessage;
+               var notXHTML = true;
+               
+               // IE bug fix
+               if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
+                       xHTML = 0;
+               
+               //If this is a xHTML message
+               if(xHTML) {
+                       notXHTML = false;
+                       
+                       // Filter the xHTML message
+                       body = filterThisXHTML(node);
+               }
+               
+               // Groupchat message
+               if(type == 'groupchat') {
+                       /* REF: http://xmpp.org/extensions/xep-0045.html */
+                       
+                       // We generate the message type and time
+                       var message_type = 'user-message';
+                       
+                       // This is an old message
+                       if(delay && resource)
+                               message_type = 'old-message';
+                       
+                       // This is a system message
+                       else if(!resource)
+                               message_type = 'system-message';
+                       
+                       var nickQuote = '';
+                       
+                       // If this is not an old message
+                       if(message_type == 'user-message') {
+                               var myNick = getMUCNick(hash);
+                               
+                               // If an user quoted our nick (with some checks)
+                               var regex = new RegExp('((^)|( )|(@))' + escapeRegex(myNick) + '(($)|(:)|(,)|( ))', 'gi');
+                               
+                               if(body.match(regex) && (myNick != resource) && (message_type == 'user-message'))
+                                       nickQuote = ' my-nick';
+                               
+                               // We notify the user if there's a new personnal message
+                               if(nickQuote) {
+                                       messageNotify(hash, 'personnal');
+                                       soundPlay(1);
+                               }
+                               
+                               // We notify the user there's a new unread muc message
+                               else
+                                       messageNotify(hash, 'unread');
+                       }
+                       
+                       // Display the received message
+                       displayMessage(type, from, hash, resource.htmlEnc(), body, time, stamp, message_type, notXHTML, nickQuote);
+               }
+               
+               // Chat message
+               else if((type == 'chat') || !type) {
+                       // Gets the nickname of the user
+                       var fromName = resource;
+                       var chatType = 'chat';
+                       
+                       // Must send a receipt notification?
+                       if(hasReceipt(message) && (id != null))
+                               sendReceived(type, from, id);
+                       
+                       // It does not come from a groupchat user, get the full name
+                       if(!GCUser)
+                               fromName = getBuddyName(xid);
+                       else
+                               chatType = 'private';
+                       
+                       // If the chat isn't yet opened, open it !
+                       if(!exists('#' + hash)) {
+                               // We create a new chat
+                               chatCreate(hash, xid, fromName, chatType);
+                               
+                               // We tell the user that a new chat has started
+                               soundPlay(0);
+                       }
+                       
+                       else
+                               soundPlay(1);
+                       
+                       // Display the received message
+                       displayMessage(type, xid, hash, fromName.htmlEnc(), body, time, stamp, 'user-message', notXHTML, '', 'him');
+                       
+                       // We notify the user
+                       messageNotify(hash, 'personnal');
+               }
+               
+               return false;
+       }
+       
+       return false;
+}
+
+// Sends a given message
+function sendMessage(hash, type) {
+       // Get the values
+       var message_area = $('#' + hash + ' .message-area');
+       var body = trim(message_area.val());
+       var xid = unescape(message_area.attr('data-to'));
+       
+       // If the user didn't entered any message, stop
+       if(!body || !xid)
+               return false;
+       
+       try {
+               // We send the message through the XMPP network
+               var aMsg = new JSJaCMessage();
+               aMsg.setTo(xid);
+               
+               // Set an ID
+               var id = genID();
+               aMsg.setID(id);
+               
+               // /help shortcut
+               if(body.match(/^\/help\s*(.*)/)) {
+                       // Help text
+                       var help_text = '<p class="help" xmlns="http://www.w3.org/1999/xhtml">';
+                       help_text += '<b>' + _e("Available shortcuts:") + '</b>';
+                       
+                       // Shortcuts array
+                       var shortcuts = [];
+                       
+                       // Common shortcuts
+                       shortcuts.push(printf(_e("%s removes the chat logs"), '<em>/clear</em>'));
+                       shortcuts.push(printf(_e("%s joins a groupchat"), '<em>/join jid</em>'));
+                       shortcuts.push(printf(_e("%s closes the chat"), '<em>/part</em>'));
+                       shortcuts.push(printf(_e("%s shows the user profile"), '<em>/whois jid</em>'));
+                       
+                       // Groupchat shortcuts
+                       if(type == 'groupchat') {
+                               shortcuts.push(printf(_e("%s sends a message to the room"), '<em>/say message</em>'));
+                               shortcuts.push(printf(_e("%s changes your nickname"), '<em>/nick nickname</em>'));
+                               shortcuts.push(printf(_e("%s sends a message to someone in the room"), '<em>/msg nickname message</em>'));
+                               shortcuts.push(printf(_e("%s changes the room topic"), '<em>/topic subject</em>'));
+                               shortcuts.push(printf(_e("%s kicks an user of the room"), '<em>/kick nickname reason</em>'));
+                               shortcuts.push(printf(_e("%s bans an user of the room"), '<em>/ban nickname reason</em>'));
+                               shortcuts.push(printf(_e("%s invites someone to join the room"), '<em>/invite jid message</em>'));
+                       }
+                       
+                       // Generate the code from the array
+                       shortcuts = shortcuts.sort();
+                       
+                       for(s in shortcuts)
+                               help_text += shortcuts[s] + '<br />';
+                       
+                       help_text += '</p>';
+                       
+                       // Display the message
+                       displayMessage(type, xid, hash, 'help', help_text, getCompleteTime(), getTimeStamp(), 'system-message', false);
+                       
+                       // Reset chatstate
+                       chatStateSend('active', xid, hash);
+               }
+               
+               // /clear shortcut
+               else if(body.match(/^\/clear/)) {
+                       cleanChat(hex_md5(xid));
+                       
+                       // Reset chatstate
+                       chatStateSend('active', xid, hash);
+               }
+               
+               // /join shortcut
+               else if(body.match(/^\/join (\S+)\s*(.*)/)) {
+                       // Join
+                       var room = generateXID(RegExp.$1, 'groupchat');
+                       var pass = RegExp.$2;
+                       
+                       checkChatCreate(room, 'groupchat');
+                       
+                       // Reset chatstate
+                       chatStateSend('active', xid, hash);
+               }
+               
+               // /part shortcut
+               else if(body.match(/^\/part\s*(.*)/) && (!isAnonymous() || (isAnonymous() && (xid != generateXID(ANONYMOUS_ROOM, 'groupchat')))))
+                       quitThisChat(xid, hex_md5(xid), type);
+               
+               // /whois shortcut
+               else if(body.match(/^\/whois(( (\S+))|($))/)) {
+                       var whois_xid = RegExp.$3;
+                       
+                       // Groupchat WHOIS
+                       if(type == 'groupchat') {
+                               var nXID = getMUCUserXID(xid, whois_xid);
+                               
+                               if(!nXID)
+                                       openThisInfo(6);
+                               else
+                                       openUserInfos(nXID);
+                       }
+                       
+                       // Chat or private WHOIS
+                       else {
+                               if(!whois_xid)
+                                       openUserInfos(xid);
+                               else
+                                       openUserInfos(whois_xid);
+                       }
+                       
+                       // Reset chatstate
+                       chatStateSend('active', xid, hash);
+               }
+               
+               // Chat message type
+               else if(type == 'chat') {
+                       aMsg.setType('chat');
+                       
+                       // Generates the correct message depending of the choosen style
+                       var notXHTML = true;
+                       var genMsg = generateMessage(aMsg, body, hash);
+                       
+                       if(genMsg == 'XHTML')
+                               notXHTML = false;
+                       
+                       // Receipt request
+                       var receipt_request = receiptRequest(hash);
+                       
+                       if(receipt_request)
+                               aMsg.appendNode('request', {'xmlns': NS_URN_RECEIPTS});
+                       
+                       // Chatstate
+                       aMsg.appendNode('active', {'xmlns': NS_CHATSTATES});
+                       
+                       // Send it!
+                       con.send(aMsg, handleErrorReply);
+                       
+                       // Filter the xHTML message (for us!)
+                       if(!notXHTML)
+                               body = filterThisXHTML(aMsg.getNode());
+                       
+                       // Finally we display the message we just sent
+                       var my_xid = getXID();
+                       
+                       displayMessage('chat', my_xid, hash, getBuddyName(my_xid).htmlEnc(), body, getCompleteTime(), getTimeStamp(), 'user-message', notXHTML, '', 'me', id);
+                       
+                       // Receipt timer
+                       if(receipt_request)
+                               checkReceived(hash, id);
+               }
+               
+               // Groupchat message type
+               else if(type == 'groupchat') {
+                       // /say shortcut
+                       if(body.match(/^\/say (.+)/)) {
+                               body = body.replace(/^\/say (.+)/, '$1');
+                               
+                               aMsg.setType('groupchat');
+                               generateMessage(aMsg, body, hash);
+                               
+                               con.send(aMsg, handleErrorReply);
+                       }
+                       
+                       // /nick shortcut
+                       else if(body.match(/^\/nick (.+)/)) {
+                               var nick = body.replace(/^\/nick (.+)/, '$1');
+                               
+                               // Does not exist yet?
+                               if(!getMUCUserXID(xid, nick)) {
+                                       // Send a new presence
+                                       sendPresence(xid + '/' + nick, '', getUserShow(), getUserStatus(), '', false, false, handleErrorReply);
+                                       
+                                       // Change the stored nickname
+                                       $('#' + hex_md5(xid)).attr('data-nick', escape(nick));
+                                       
+                                       // Reset chatstate
+                                       chatStateSend('active', xid, hash);
+                               }
+                       }
+                       
+                       // /msg shortcut
+                       else if(body.match(/^\/msg (\S+)\s+(.+)/)) {
+                               var nick = RegExp.$1;
+                               var body = RegExp.$2;
+                               var nXID = getMUCUserXID(xid, nick);
+                               
+                               // We check if the user exists
+                               if(!nXID)
+                                       openThisInfo(6);
+                               
+                               // If the private message is not empty
+                               else if(body) {
+                                       aMsg.setType('chat');
+                                       aMsg.setTo(nXID);
+                                       generateMessage(aMsg, body, hash);
+                                       
+                                       con.send(aMsg, handleErrorReply);
+                               }
+                       }
+                       
+                       // /topic shortcut
+                       else if(body.match(/^\/topic (.+)/)) {
+                               var topic = body.replace(/^\/topic (.+)/, '$1');
+                               
+                               aMsg.setType('groupchat');
+                               aMsg.setSubject(topic);
+                               
+                               con.send(aMsg, handleMessageError);
+                               
+                               // Reset chatstate
+                               chatStateSend('active', xid, hash);
+                       }
+                       
+                       // /ban shortcut
+                       else if(body.match(/^\/ban (\S+)\s*(.*)/)) {
+                               var nick = RegExp.$1;
+                               var reason = RegExp.$2;
+                               var nXID = getMUCUserRealXID(xid, nick);
+                               
+                               // We check if the user exists
+                               if(!nXID)
+                                       openThisInfo(6);
+                               
+                               else {
+                                       // We generate the ban IQ
+                                       var iq = new JSJaCIQ();
+                                       iq.setTo(xid);
+                                       iq.setType('set');
+                                       
+                                       var iqQuery = iq.setQuery(NS_MUC_ADMIN);
+                                       var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': nXID, 'xmlns': NS_MUC_ADMIN}));
+                                       
+                                       if(reason)
+                                               item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
+                                       
+                                       con.send(iq, handleErrorReply);
+                               }
+                               
+                               // Reset chatstate
+                               chatStateSend('active', xid, hash);
+                       }
+                       
+                       // /kick shortcut
+                       else if(body.match(/^\/kick (\S+)\s*(.*)/)) {
+                               var nick = RegExp.$1;
+                               var reason = RegExp.$2;
+                               var nXID = getMUCUserXID(xid, nick);
+                               
+                               // We check if the user exists
+                               if(!nXID)
+                                       openThisInfo(6);
+                               
+                               else {
+                                       // We generate the kick IQ
+                                       var iq = new JSJaCIQ();
+                                       iq.setTo(xid);
+                                       iq.setType('set');
+                                       
+                                       var iqQuery = iq.setQuery(NS_MUC_ADMIN);
+                                       var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
+                                       
+                                       if(reason)
+                                               item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
+                                       
+                                       con.send(iq, handleErrorReply);
+                               }
+                               
+                               // Reset chatstate
+                               chatStateSend('active', xid, hash);
+                       }
+                       
+                       // /invite shortcut
+                       else if(body.match(/^\/invite (\S+)\s*(.*)/)) {
+                               var i_xid = RegExp.$1;
+                               var reason = RegExp.$2;
+                               
+                               var x = aMsg.appendNode('x', {'xmlns': NS_MUC_USER});
+                               var aNode = x.appendChild(aMsg.buildNode('invite', {'to': i_xid, 'xmlns': NS_MUC_USER}));
+                               
+                               if(reason)
+                                       aNode.appendChild(aMsg.buildNode('reason', {'xmlns': NS_MUC_USER}, reason));
+                               
+                               con.send(aMsg, handleErrorReply);
+                               
+                               // Reset chatstate
+                               chatStateSend('active', xid, hash);
+                       }
+                       
+                       // No shortcut, this is a message
+                       else {
+                               aMsg.setType('groupchat');
+                               
+                               // Chatstate
+                               aMsg.appendNode('active', {'xmlns': NS_CHATSTATES});
+                               
+                               generateMessage(aMsg, body, hash);
+                               
+                               con.send(aMsg, handleMessageError);
+                               
+                               logThis('Message sent to: ' + xid + ' / ' + type, 3);
+                       }
+               }
+               
+               // We reset the message input
+               $('#' + hash + ' .message-area').val('');
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+// Generates the correct message area style
+function generateStyle(hash) {
+       // Initialize the vars
+       var styles = '#' + hash + ' div.bubble-style';
+       var checkbox = styles + ' input[type=checkbox]';
+       var color = styles + ' a.color.selected';
+       var style = '';
+       
+       // Loop the input values
+       $(checkbox).filter(':checked').each(function() {
+               // If there is a previous element
+               if(style)
+                       style += ' ';
+               
+               // Get the current style
+               switch($(this).attr('class')) {
+                       case 'bold':
+                               style += 'font-weight: bold;';
+                               break;
+                       
+                       case 'italic':
+                               style += 'font-style: italic;';
+                               break;
+                       
+                       case 'underline':
+                               style += 'text-decoration: underline;';
+                               break;
+               }
+       });
+       
+       // Get the color value
+       $(color).each(function() {
+               style += 'color: #' + $(this).attr('data-color');
+       });
+       
+       return style;
+}
+
+// Generates the correct message code
+function generateMessage(aMsg, body, hash) {
+       // Create the classical body
+       aMsg.setBody(body);
+       
+       // Get the style
+       var style = $('#' + hash + ' .message-area').attr('style');
+       
+       // A message style is choosen
+       if(style) {
+               // Explode the message body new lines (to create one <p /> element by line)
+               var new_lines = new Array(body);
+               
+               if(body.match(/\n/))
+                       new_lines = body.split('\n');
+               
+               // Create the XML elements
+               var aHtml = aMsg.appendNode('html', {'xmlns': NS_XHTML_IM});
+               var aBody = aHtml.appendChild(aMsg.buildNode('body', {'xmlns': NS_XHTML}));
+               
+               // Use the exploded body array to create one element per entry
+               for(i in new_lines) {
+                       // Current line
+                       var cLine = new_lines[i];
+                       
+                       // Blank line, we put a <br />
+                       if(cLine.match(/(^)(\s+)($)/) || !cLine)
+                               aBody.appendChild(aMsg.buildNode('br', {'xmlns': NS_XHTML}));
+                       
+                       // Line with content, we put a <p />
+                       else {
+                               // HTML encode the line
+                               cLine = cLine.htmlEnc();
+                               
+                               // Filter the links
+                               cLine = applyLinks(cLine, 'xhtml-im', style);
+                               
+                               // Append the filtered line
+                               $(aBody).append($('<p style="' + style + '">' + cLine + '</p>'));
+                       }
+               }
+               
+               return 'XHTML';
+       }
+       
+       return 'PLAIN';
+}
+
+// Displays a given message in a chat tab
+function displayMessage(type, xid, hash, name, body, time, stamp, message_type, is_xhtml, nick_quote, mode, id) {
+       // Generate some stuffs
+       var has_avatar = false;
+       var xid_hash = '';
+       
+       if(!nick_quote)
+               nick_quote = '';
+       
+       if(message_type != 'system-message') {
+               has_avatar = true;
+               xid_hash = hex_md5(xid);
+       }
+       
+       // Can scroll?
+       var cont_scroll = document.getElementById('chat-content-' + hash);
+       var can_scroll = false;
+       
+       if(!cont_scroll.scrollTop || ((cont_scroll.clientHeight + cont_scroll.scrollTop) == cont_scroll.scrollHeight))
+               can_scroll = true;
+       
+       // Any ID?
+       var data_id = '';
+       
+       if(id)
+               data_id = ' data-id="' + id + '"';
+       
+       // Filter the message
+       var filteredMessage = filterThisMessage(body, name, is_xhtml);
+       
+       // Display the received message in the room
+       var messageCode = '<div class="one-line ' + message_type + nick_quote + '"' + data_id + '>';
+       
+       // Name color attribute
+       if(type == 'groupchat')
+               attribute = ' style="color: ' + generateColor(name) + ';" class="name';
+       else {
+               attribute = ' class="name';
+               
+               if(mode)
+                       attribute += ' ' + mode;
+       }
+       
+       // Close the class attribute
+       if(message_type == 'system-message')
+               attribute += ' hidden"';
+       else
+               attribute += '"';
+       
+       // Filter the previous displayed message
+       var last = $('#' + hash + ' .one-group:last');
+       var last_name = last.find('b.name').attr('data-xid');
+       var last_type = last.attr('data-type');
+       var last_stamp = parseInt(last.attr('data-stamp'));
+       var grouped = false;
+       
+       // We can group it with another previous message
+       if((last_name == xid) && (message_type == last_type) && ((stamp - last_stamp) <= 1800))
+               grouped = true;
+       
+       // Is it a /me command?
+       if(body.match(/(^|>)(\/me )([^<]+)/))
+               filteredMessage = '<i>' + filteredMessage + '</i>';
+       
+       messageCode += filteredMessage + '</div>';
+       
+       // Must group it?
+       var group_path = ' .one-group:last';
+       
+       if(!grouped) {
+               // Generate message headers
+               var message_head = '';
+               
+               // Any avatar to add?
+               if(has_avatar)
+                       message_head += '<div class="avatar-container"><img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" /></div>';
+               
+               // Add the date & the name
+               message_head += '<span class="date">' + time + '</span><b data-xid="' + encodeQuotes(xid) + '" ' + attribute + '>' + name + '</b>';
+               
+               // Generate message code
+               group_path = '';
+               messageCode = '<div class="one-group ' + xid_hash + '" data-type="' + message_type + '" data-stamp="' + stamp + '">' + message_head + messageCode + '</div>';
+       }
+       
+       // Archive message
+       if(hash == 'archives')
+               $('#archives .logs' + group_path).append(messageCode);
+       
+       // Instant message
+       else {
+               // Write the code in the DOM
+               $('#' + hash + ' .content' + group_path).append(messageCode);
+               
+               // Must get the avatar?
+               if(has_avatar && xid)
+                       getAvatar(xid, 'cache', 'true', 'forget');
+       }
+       
+       // Scroll to this message
+       if(can_scroll)
+               autoScroll(hash);
+}
diff --git a/jappixmini/jappix/js/microblog.js b/jappixmini/jappix/js/microblog.js
new file mode 100644 (file)
index 0000000..ceff07a
--- /dev/null
@@ -0,0 +1,1447 @@
+/*
+
+Jappix - An open social platform
+These are the microblog JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/12/11
+
+*/
+
+// Completes arrays of an entry's attached files
+function attachedMicroblog(selector, tFName, tFURL, tFThumb, tFSource, tFType, tFLength, tFEComments, tFNComments) {
+       if($(selector).attr('title'))
+               tFName.push($(selector).attr('title'));
+       else
+               tFName.push('');
+       
+       if($(selector).attr('href'))
+               tFURL.push($(selector).attr('href'));
+       else
+               tFURL.push('');
+       
+       if($(selector).find('link[rel=self][title=thumb]:first').attr('href'))
+               tFThumb.push($(selector).find('link[rel=self][title=thumb]:first').attr('href'));
+       else
+               tFThumb.push('');
+       
+       if($(selector).attr('source'))
+               tFSource.push($(selector).attr('source'));
+       else
+               tFSource.push('');
+       
+       if($(selector).attr('type'))
+               tFType.push($(selector).attr('type'));
+       else
+               tFType.push('');
+       
+       if($(selector).attr('length'))
+               tFLength.push($(selector).attr('length'));
+       else
+               tFLength.push('');
+       
+       // Comments?
+       var comments_href_c = $(selector).find('link[rel=replies][title=comments_file]:first').attr('href');
+       
+       if(comments_href_c && comments_href_c.match(/^xmpp:(.+)\?;node=(.+)/)) {
+               tFEComments.push(RegExp.$1);
+               tFNComments.push(decodeURIComponent(RegExp.$2));
+       }
+       
+       else {
+               tFEComments.push('');
+               tFNComments.push('');
+       }
+}
+
+// Displays a given microblog item
+function displayMicroblog(packet, from, hash, mode, way) {
+       // Get some values
+       var iParse = $(packet.getNode()).find('items item');
+       
+       iParse.each(function() {
+               // Initialize
+               var tTitle, tFiltered, tTime, tDate, tStamp, tBody, tName, tID, tHash, tIndividual, tFEClick;
+               
+               // Arrays
+               var tFName = [];
+               var tFURL = [];
+               var tFThumb = [];
+               var tFSource = [];
+               var tFType = [];
+               var tFLength = [];
+               var tFEComments = [];
+               var tFNComments = [];
+               var aFURL = [];
+               var aFCat = [];
+               
+               // Get the values
+               tDate = $(this).find('published').text();
+               tBody = $(this).find('body').text();
+               tID = $(this).attr('id');
+               tName = getBuddyName(from);
+               tHash = 'update-' + hex_md5(tName + tDate + tID);
+               
+               // Read attached files with a thumb (place them at first)
+               $(this).find('link[rel=enclosure]:has(link[rel=self][title=thumb])').each(function() {
+                       attachedMicroblog(this, tFName, tFURL, tFThumb, tFSource, tFType, tFLength, tFEComments, tFNComments);
+               });
+               
+               // Read attached files without any thumb
+               $(this).find('link[rel=enclosure]:not(:has(link[rel=self][title=thumb]))').each(function() {
+                       attachedMicroblog(this, tFName, tFURL, tFThumb, tFSource, tFType, tFLength, tFEComments, tFNComments);
+               });
+               
+               // Get the repeat value
+               var uRepeat = [$(this).find('source author name').text(), explodeThis(':', $(this).find('source author uri').text(), 1)];
+               var uRepeated = false;
+               
+               if(!uRepeat[0])
+                       uRepeat = [getBuddyName(from), uRepeat[1]];
+               if(!uRepeat[1])
+                       uRepeat = [uRepeat[0], from];
+               
+               // Repeated?
+               if(uRepeat[1] != from)
+                       uRepeated = true;
+               
+               // Get the comments node
+               var entityComments, nodeComments;
+               
+               // Get the comments
+               var comments_href = $(this).find('link[title=comments]:first').attr('href');
+               
+               if(comments_href && comments_href.match(/^xmpp:(.+)\?;node=(.+)/)) {
+                       entityComments = RegExp.$1;
+                       nodeComments = decodeURIComponent(RegExp.$2);
+               }
+               
+               // No comments node?
+               if(!entityComments || !nodeComments) {
+                       entityComments = '';
+                       nodeComments = '';
+               }
+               
+               // Get the stamp & time
+               if(tDate) {
+                       tStamp = extractStamp(Date.jab2date(tDate));
+                       tTime = relativeDate(tDate);
+               }
+               
+               else {
+                       tStamp = getTimeStamp();
+                       tTime = '';
+               }
+               
+               // Get the item geoloc
+               var tGeoloc = '';
+               var sGeoloc = $(this).find('geoloc[xmlns=' + NS_GEOLOC + ']:first');
+               var gLat = sGeoloc.find('lat').text();
+               var gLon = sGeoloc.find('lon').text();
+               
+               if(gLat && gLon) {
+                       tGeoloc += '<a class="geoloc talk-images" href="http://maps.google.com/?q=' + encodeQuotes(gLat) + ',' + encodeQuotes(gLon) + '" target="_blank">';
+                       
+                       // Human-readable name?
+                       var gHuman = humanPosition(
+                                          sGeoloc.find('locality').text(),
+                                          sGeoloc.find('region').text(),
+                                          sGeoloc.find('country').text()
+                                         );
+                       
+                       if(gHuman)
+                               tGeoloc += gHuman.htmlEnc();
+                       else
+                               tGeoloc += gLat.htmlEnc() + '; ' + gLon.htmlEnc();
+                       
+                       tGeoloc += '</a>';
+               }
+               
+               // Retrieve the message body
+               tTitle = $(this).find('content[type=text]').text();
+               
+               if(!tTitle) {
+                       // Legacy?
+                       tTitle = $(this).find('title:not(source > title)').text();
+                       
+                       // Last chance?
+                       if(!tTitle)
+                               tTitle = tBody;
+               }
+               
+               // Trim the content
+               tTitle = trim(tTitle);
+               
+               // Any content?
+               if(tTitle) {
+                       // Apply links to message body
+                       tFiltered = filterThisMessage(tTitle, tName.htmlEnc(), true);
+                       
+                       // Display the received message
+                       var html = '<div class="one-update update_' + hash + ' ' + tHash + '" data-stamp="' + encodeQuotes(tStamp) + '" data-id="' + encodeQuotes(tID) + '" data-xid="' + encodeQuotes(from) + '">' + 
+                                       '<div class="' + hash + '">' + 
+                                               '<div class="avatar-container">' + 
+                                                       '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                               '</div>' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="body">' + 
+                                               '<p>';
+                       
+                       // Is it a repeat?
+                       if(uRepeated)
+                               html += '<a href="#" class="repeat talk-images" title="' + encodeQuotes(printf(_e("This is a repeat from %s"), uRepeat[0] + ' (' + uRepeat[1] + ')')) + '" onclick="return checkChatCreate(\'' + encodeOnclick(uRepeat[1]) + '\', \'chat\');" data-xid="' + encodeQuotes(uRepeat[1]) + '"></a>';
+                       
+                       html += '<b title="' + from + '" class="name">' + tName.htmlEnc() + '</b> <span>' + tFiltered + '</span></p>' + 
+                               '<p class="infos">' + tTime + tGeoloc + '</p>';
+                       
+                       // Any file to display?
+                       if(tFURL.length)
+                               html += '<p class="file">';
+                       
+                       // Generate an array of the files URL
+                       for(var a = 0; a < tFURL.length; a++) {
+                               // Not enough data?
+                               if(!tFURL[a])
+                                       continue;
+                               
+                               // Push the current URL! (YouTube or file)
+                               if(tFURL[a].match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim)) {
+                                       aFURL.push(trim(RegExp.$8));
+                                       aFCat.push('youtube');
+                               }
+                               
+                               else if(canIntegrateBox(explodeThis('/', tFType[a], 1))) {
+                                       aFURL.push(tFURL[a]);
+                                       aFCat.push(fileCategory(explodeThis('/', tFType[a], 1)));
+                               }
+                       }
+                       
+                       // Add each file code
+                       for(var f = 0; f < tFURL.length; f++) {
+                               // Not enough data?
+                               if(!tFURL[f])
+                                       continue;
+                               
+                               // Get the file type
+                               var tFExt = explodeThis('/', tFType[f], 1);
+                               var tFCat = fileCategory(tFExt);
+                               var tFLink = tFURL[f];
+                               
+                               // Youtube video?
+                               if(tFLink.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim)) {
+                                       tFLink = trim(RegExp.$8);
+                                       tFCat = 'youtube';
+                               }
+                               
+                               // Supported image/video/sound
+                               if(canIntegrateBox(tFExt) || (tFCat == 'youtube'))
+                                       tFEClick = 'onclick="return applyIntegrateBox(\'' + encodeOnclick(tFLink) + '\', \'' + encodeOnclick(tFCat) + '\', \'' + encodeOnclick(aFURL) + '\', \'' + encodeOnclick(aFCat) + '\', \'' + encodeOnclick(tFEComments) + '\', \'' + encodeOnclick(tFNComments) + '\', \'large\');" ';
+                               else
+                                       tFEClick = '';
+                               
+                               // Any thumbnail?
+                               if(tFThumb[f])
+                                       html += '<a class="thumb" ' + tFEClick + 'href="' + encodeQuotes(tFURL[f]) + '" target="_blank" title="' + encodeQuotes(tFName[f]) + '" data-node="' + encodeQuotes(tFNComments) + '"><img src="' + encodeQuotes(tFThumb[f]) + '" alt="" /></a>';
+                               else
+                                       html += '<a class="' + encodeQuotes(tFCat) + ' link talk-images" ' + tFEClick + 'href="' + encodeQuotes(tFURL[f]) + '" target="_blank" data-node="' + encodeQuotes(tFNComments) + '">' + tFName[f].htmlEnc() + '</a>';
+                       }
+                       
+                       if(tFURL.length)
+                               html += '</p>';
+                       
+                       // It's my own notice, we can remove it!
+                       if(from == getXID())
+                               html += '<a href="#" onclick="return removeMicroblog(\'' + encodeOnclick(tID) + '\', \'' + encodeOnclick(tHash) + '\');" title="' + _e("Remove this notice") + '" class="mbtool remove talk-images"></a>';
+                       
+                       // Notice from another user
+                       else {
+                               // User profile
+                               html += '<a href="#" title="' + _e("View profile") + '" class="mbtool profile talk-images" onclick="return openUserInfos(\'' + encodeOnclick(from) + '\');"></a>';
+                               
+                               // If PEP is enabled
+                               if(enabledPEP())
+                                       html += '<a href="#" title="' + _e("Repeat this notice") + '" class="mbtool repost talk-images"></a>';
+                       }
+                       
+                       html += '</div><div class="comments-container" data-node="' + encodeQuotes(nodeComments) + '"></div></div>';
+                       
+                       // Mixed mode
+                       if((mode == 'mixed') && !exists('.mixed .' + tHash)) {
+                               // Remove the old element
+                               if(way == 'push')
+                                       $('#channel .content.mixed .one-update.update_' + hash).remove();
+                               
+                               // Get the nearest element
+                               var nearest = sortElementByStamp(tStamp, '#channel .mixed .one-update');
+                               
+                               // Append the content at the right position (date relative)
+                               if(nearest == 0)
+                                       $('#channel .content.mixed').append(html);
+                               else
+                                       $('#channel .one-update[data-stamp=' + nearest + ']:first').before(html);
+                               
+                               // Show the new item
+                               if(way == 'push')
+                                       $('#channel .content.mixed .one-update.' + tHash).fadeIn('fast');
+                               else
+                                       $('#channel .content.mixed .one-update.' + tHash).show();
+                               
+                               // Remove the old notices to make the DOM lighter
+                               var oneUpdate = '#channel .content.mixed .one-update';
+                               
+                               if($(oneUpdate).size() > 80)
+                                       $(oneUpdate + ':last').remove();
+                               
+                               // Click event on avatar/name
+                               $('.mixed .' + tHash + ' .avatar-container, .mixed .' + tHash + ' .body b').click(function() {
+                                       getMicroblog(from, hash);
+                               });
+                       }
+                       
+                       // Individual mode
+                       tIndividual = '#channel .content.individual.microblog-' + hash;
+                       
+                       // Can append individual content?
+                       var can_individual = true;
+                       
+                       if($('#channel .top.individual input[name=comments]').val() && exists(tIndividual + ' .one-update'))
+                               can_individual = false;
+                       
+                       if(can_individual && exists(tIndividual) && !exists('.individual .' + tHash)) {
+                               if(mode == 'mixed')
+                                       $(tIndividual).prepend(html);
+                               else
+                                       $(tIndividual + ' a.more').before(html);
+                               
+                               // Show the new item
+                               if(way == 'push')
+                                       $('#channel .content.individual .one-update.' + tHash).fadeIn('fast');
+                               else
+                                       $('#channel .content.individual .one-update.' + tHash).show();
+                               
+                               // Make 'more' link visible
+                               $(tIndividual + ' a.more').css('visibility', 'visible');
+                               
+                               // Click event on name (if not me!)
+                               if(from != getXID())
+                                       $('.individual .' + tHash + ' .avatar-container, .individual .' + tHash + ' .body b').click(function() {
+                                               checkChatCreate(from, 'chat');
+                                       });
+                       }
+                       
+                       // Apply the click event
+                       $('.' + tHash + ' a.repost:not([data-event=true])').click(function() {
+                               return publishMicroblog(tTitle, tFName, tFURL, tFType, tFLength, tFThumb, uRepeat, entityComments, nodeComments, tFEComments, tFNComments);
+                       })
+                       
+                       .attr('data-event', 'true');
+                       
+                       // Apply the hover event
+                       if(nodeComments)
+                               $('.' + mode + ' .' + tHash).hover(function() {
+                                       showCommentsMicroblog($(this), entityComments, nodeComments, tHash);
+                               }, function() {
+                                       if($(this).find('div.comments a.one-comment.loading').size())
+                                               $(this).find('div.comments').remove();
+                               });
+               }
+       });
+       
+       // Display the avatar of this buddy
+       getAvatar(from, 'cache', 'true', 'forget');
+}
+
+// Removes a given microblog item
+function removeMicroblog(id, hash) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#publisher-delete */
+       
+       // Initialize
+       var selector = $('.' + hash);
+       var get_last = false;
+       
+       // Get the latest item for the mixed mode
+       if(exists('#channel .content.mixed .' + hash))
+               get_last = true;
+       
+       // Remove the item from our DOM
+       selector.fadeOut('fast', function() {
+               $(this).remove();
+       });
+       
+       // Send the IQ to remove the item (and get eventual error callback)
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var retract = pubsub.appendChild(iq.buildNode('retract', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB}));
+       retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+       
+       if(get_last)
+               con.send(iq, handleRemoveMicroblog);
+       else
+               con.send(iq, handleErrorReply);
+       
+       return false;
+}
+
+// Handles the microblog item removal
+function handleRemoveMicroblog(iq) {
+       // Handle the error reply
+       handleErrorReply(iq);
+       
+       // Get the latest item
+       requestMicroblog(getXID(), '1', false, handleUpdateRemoveMicroblog);
+}
+
+// Handles the microblog update
+function handleUpdateRemoveMicroblog(iq) {
+       // Error?
+       if(iq.getType() == 'error')
+               return;
+       
+       // Initialize
+       var xid = bareXID(getStanzaFrom(iq));
+       var hash = hex_md5(xid);
+       
+       // Display the item!
+       displayMicroblog(iq, xid, hash, 'mixed', 'push');
+}
+
+// Gets a given microblog comments node
+function getCommentsMicroblog(server, node, id) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#subscriber-retrieve-requestall */
+       
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setID('get_' + genID() + '-' + id);
+       iq.setTo(server);
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       pubsub.appendChild(iq.buildNode('items', {'node': node, 'xmlns': NS_PUBSUB}));
+       
+       con.send(iq, handleCommentsMicroblog);
+       
+       return false;
+}
+
+// Handles a microblog comments node items
+function handleCommentsMicroblog(iq) {
+       // Path
+       var id = explodeThis('-', iq.getID(), 1);
+       var path = 'div.comments[data-id=' + id + '] div.comments-content';
+       
+       // Does not exist?
+       if(!exists(path))
+               return false;
+       
+       // Any error?
+       if(handleErrorReply(iq)) {
+               $(path).html('<div class="one-comment loading">' + _e("Could not get the comments!") + '</div>');
+               
+               return false;
+       }
+       
+       // Initialize
+       var data = iq.getNode();
+       var server = bareXID(getStanzaFrom(iq));
+       var node = $(data).find('items:first').attr('node');
+       var users_xid = [];
+       var code = '';
+       
+       // No node?
+       if(!node)
+               node = $(data).find('publish:first').attr('node');
+       
+       // Get the parent microblog item
+       var parent_select = $('#channel .one-update:has(*[data-node=' + node + '])');
+       var parent_data = [parent_select.attr('data-xid'), NS_URN_MBLOG, parent_select.attr('data-id')];
+       
+       // Get the owner XID
+       var owner_xid = parent_select.attr('data-xid');
+       var repeat_xid = parent_select.find('a.repeat').attr('data-xid');
+       
+       // Must we create the complete DOM?
+       var complete = true;
+       
+       if($(path).find('.one-comment.compose').size())
+               complete = false;
+       
+       // Add the comment tool
+       if(complete)
+               code += '<div class="one-comment compose">' + 
+                               '<span class="icon talk-images"></span><input type="text" placeholder="' + _e("Type your comment here...") + '" />' + 
+                       '</div>';
+       
+       // Append the comments
+       $(data).find('item').each(function() {
+               // Get comment
+               var current_id = $(this).attr('id');
+               var current_xid = explodeThis(':', $(this).find('source author uri').text(), 1);
+               var current_name = $(this).find('source author name').text();
+               var current_date = $(this).find('published').text();
+               var current_body = $(this).find('content[type=text]').text();
+               var current_bname = getBuddyName(current_xid);
+               
+               // Legacy?
+               if(!current_body)
+                       current_body = $(this).find('title:not(source > title)').text();
+               
+               // Yet displayed? (continue the loop)
+               if($(path).find('.one-comment[data-id=' + current_id + ']').size())
+                       return;
+               
+               // No XID?
+               if(!current_xid) {
+                       current_xid = '';
+                       
+                       if(!current_name)
+                               current_name = _e("unknown");
+               }
+               
+               else if(!current_name || (current_bname != getXIDNick(current_xid)))
+                       current_name = current_bname;
+               
+               // Any date?
+               if(current_date)
+                       current_date = relativeDate(current_date);
+               else
+                       current_date = getCompleteTime();
+               
+               // Click event
+               var onclick = 'false';
+               
+               if(current_xid != getXID())
+                       onclick = 'checkChatCreate(\'' + encodeOnclick(current_xid) + '\', \'chat\')';
+               
+               // If this is my comment, add a marker
+               var type = 'him';
+               var marker = '';
+               var remove = '';
+               
+               if(current_xid == getXID()) {
+                       type = 'me';
+                       marker = '<div class="marker"></div>';
+                       remove = '<a href="#" class="remove" onclick="return removeCommentMicroblog(\'' + encodeOnclick(server) + '\', \'' + encodeOnclick(node) + '\', \'' + encodeOnclick(current_id) + '\');">' + _e("Remove") + '</a>';
+               }
+               
+               // New comment?
+               var new_class = '';
+               
+               if(!complete)
+                       new_class = ' new';
+               
+               // Add the comment
+               if(current_body) {
+                       // Add the XID
+                       if(!existArrayValue(users_xid, current_xid))
+                               users_xid.push(current_xid);
+                       
+                       // Add the HTML code
+                       code += '<div class="one-comment ' + hex_md5(current_xid) + ' ' + type + new_class + '" data-id="' + encodeQuotes(current_id) + '">' + 
+                                       marker + 
+                                       
+                                       '<div class="avatar-container" onclick="return ' + onclick + ';">' + 
+                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="comment-container">' + 
+                                               '<a href="#" onclick="return ' + onclick + ';" title="' + encodeQuotes(current_xid) + '" class="name">' + current_name.htmlEnc() + '</a>' + 
+                                               '<span class="date">' + current_date.htmlEnc() + '</span>' + 
+                                               remove + 
+                                       
+                                               '<p class="body">' + filterThisMessage(current_body, current_name, true) + '</p>' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="clear"></div>' + 
+                               '</div>';
+               }
+       });
+       
+       // Add the HTML
+       if(complete) {
+               $(path).html(code);
+               
+               // Focus on the compose input
+               $(document).oneTime(10, function() {
+                       $(path).find('.one-comment.compose input').focus();
+               });
+       }
+       
+       else {
+               $(path).find('.one-comment.compose').after(code);
+               
+               // Beautiful effect
+               $(path).find('.one-comment.new').slideDown('fast', function() {
+                       adaptCommentMicroblog(id);
+               }).removeClass('new');
+       }
+       
+       // Set the good widths
+       adaptCommentMicroblog(id);
+       
+       // Get the avatars
+       for(a in users_xid)
+               getAvatar(users_xid[a], 'cache', 'true', 'forget');
+       
+       // Add the owner XID
+       if(owner_xid && owner_xid.match('@') && !existArrayValue(users_xid, owner_xid))
+               users_xid.push(owner_xid);
+       
+       // Add the repeated from XID
+       if(repeat_xid && repeat_xid.match('@') && !existArrayValue(users_xid, repeat_xid))
+               users_xid.push(repeat_xid);
+       
+       // Remove my own XID
+       removeArrayValue(users_xid, getXID());
+       
+       // DOM events
+       if(complete) {
+               // Update timer
+               $(path).everyTime('60s', function() {
+                       getCommentsMicroblog(server, node, id);
+                       
+                       logThis('Updating comments node: ' + node + ' on ' + server + '...');
+               });
+               
+               // Input key event
+               $(path).find('.one-comment.compose input').placeholder()
+                                    .keyup(function(e) {
+                                               if((e.keyCode == 13) && $(this).val()) {
+                                                       // Send the comment!
+                                                       sendCommentMicroblog($(this).val(), server, node, id, users_xid, parent_data);
+                                                       
+                                                       // Reset the input value
+                                                       $(this).val('');
+                                                       
+                                                       return false;
+                                               }
+                                    });
+       }
+}
+
+// Shows the microblog comments box
+function showCommentsMicroblog(path, entityComments, nodeComments, tHash) {
+       // Do not display it twice!
+       if(path.find('div.comments').size())
+               return;
+       
+       // Generate an unique ID
+       var idComments = genID();
+       
+       // Create comments container
+       path.find('div.comments-container').append(
+               '<div class="comments" data-id="' + encodeQuotes(idComments) + '">' + 
+                       '<div class="arrow talk-images"></div>' + 
+                       '<div class="comments-content">' + 
+                               '<a href="#" class="one-comment loading"><span class="icon talk-images"></span>' + _e("Show comments") + '</a>' + 
+                       '</div>' + 
+               '</div>'
+       );
+       
+       // Click event
+       path.find('div.comments a.one-comment').click(function() {
+               // Set loading info
+               $(this).parent().html('<div class="one-comment loading"><span class="icon talk-images"></span>' + _e("Loading comments...") + '</div>');
+               
+               // Request comments
+               getCommentsMicroblog(entityComments, nodeComments, idComments);
+               
+               // Remove the comments from the DOM if click away
+               if(tHash) {
+                       $('#channel').die('click');
+                       
+                       $('#channel').live('click', function(evt) {
+                               if(!$(evt.target).parents('.' + tHash).size()) {
+                                       $('#channel').die('click');
+                                       $('#channel .one-update div.comments-content').stopTime();
+                                       $('#channel .one-update div.comments').remove();
+                               }
+                       });
+               }
+               
+               return false;
+       });
+}
+
+// Sends a comment on a given microblog comments node
+function sendCommentMicroblog(value, server, node, id, notifiy_arr, parent_data) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#publisher-publish */
+       
+       // Not enough data?
+       if(!value || !server || !node)
+               return false;
+       
+       // Get some values
+       var date = getXMPPTime('utc');
+       var hash = hex_md5(value + date);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       iq.setTo(server);
+       iq.setID('set_' + genID() + '-' + id);
+       
+       // PubSub main elements
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': node, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'id': hash, 'xmlns': NS_PUBSUB}));
+       var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
+       
+       // Author infos
+       var Source = entry.appendChild(iq.buildNode('source', {'xmlns': NS_ATOM}));
+       var author = Source.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
+       author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, getName()));
+       author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + getXID()));
+       
+       // Create the comment
+       entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, value));
+       entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, date));
+       
+       con.send(iq);
+       
+       // Handle this comment!
+       iq.setFrom(server);
+       handleCommentsMicroblog(iq);
+       
+       // Notify users
+       if(notifiy_arr && notifiy_arr.length) {
+               // XMPP link to the item
+               var href = 'xmpp:' + server + '?;node=' + encodeURIComponent(node) + ';item=' + encodeURIComponent(hash);
+               
+               // Loop!
+               for(n in notifiy_arr)
+                       sendNotification(notifiy_arr[n], 'comment', href, value, parent_data);
+       }
+       
+       return false;
+}
+
+// Removes a given microblog comment item
+function removeCommentMicroblog(server, node, id) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#publisher-delete */
+       
+       // Remove the item from our DOM
+       $('.one-comment[data-id=' + id + ']').slideUp('fast', function() {
+               // Get the parent ID
+               var parent_id = $(this).parents('div.comments').attr('data-id');
+               
+               // Remove it!
+               $(this).remove();
+               
+               // Adapt the width
+               adaptCommentMicroblog(parent_id);
+       });
+       
+       // Send the IQ to remove the item (and get eventual error callback)
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       iq.setTo(server);
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var retract = pubsub.appendChild(iq.buildNode('retract', {'node': node, 'xmlns': NS_PUBSUB}));
+       retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+       
+       con.send(iq);
+       
+       return false;
+}
+
+// Adapts the comment elements width
+function adaptCommentMicroblog(id) {
+       var selector = $('div.comments[data-id=' + id + '] div.comments-content');
+       var selector_width = selector.width();
+       
+       // Change widths
+       selector.find('.one-comment.compose input').css('width', selector_width - 60);
+       selector.find('.one-comment .comment-container').css('width', selector_width - 55);
+}
+
+// Handles the microblog of an user
+function handleMicroblog(iq) {
+       // Get the from attribute of this IQ
+       var from = bareXID(getStanzaFrom(iq));
+       
+       // Define the selector path
+       var selector = '#channel .top.individual input[name=';
+       
+       // Is this request still alive?
+       if(from == $(selector + 'jid]').val()) {
+               var hash = hex_md5(from);
+               
+               // Update the items counter
+               var old_count = parseInt($(selector + 'counter]').val());
+               $(selector + 'counter]').val(old_count + 20);
+               
+               // Display the microblog
+               displayMicroblog(iq, from, hash, 'individual', 'request');
+               
+               // Hide the waiting icon
+               if(enabledPEP())
+                       waitMicroblog('sync');
+               else
+                       waitMicroblog('unsync');
+               
+               // Hide the 'more items' link?
+               if($(iq.getNode()).find('item').size() < old_count)
+                       $('#channel .individual a.more').remove();
+               
+               // Get the comments?
+               var comments_node = $('#channel .top.individual input[name=comments]').val();
+               
+               if(comments_node && comments_node.match(/^xmpp:(.+)\?;node=(.+);item=(.+)/)) {
+                       // Get the values
+                       var comments_entity = RegExp.$1;
+                       comments_node = decodeURIComponent(RegExp.$2);
+                       
+                       // Selectors
+                       var file_link = $('#channel .individual .one-update p.file a[data-node=' + comments_node + ']');
+                       var entry_link = $('#channel .individual .one-update:has(*[data-node=' + comments_node + '])');
+                       
+                       // Is it a file?
+                       if(file_link.size())
+                               file_link.click();
+                       
+                       // Is it a microblog entry?
+                       else if(entry_link.size()) {
+                               showCommentsMicroblog(entry_link, comments_entity, comments_node);
+                               entry_link.find('a.one-comment').click();
+                       }
+               }
+       }
+       
+       logThis('Microblog got: ' + from, 3);
+}
+
+// Resets the microblog elements
+function resetMicroblog() {
+       // Reset everything
+       $('#channel .individual .one-update div.comments-content').stopTime();
+       $('#channel .individual').remove();
+       $('#channel .mixed').show();
+       
+       // Hide the waiting icon
+       if(enabledPEP())
+               waitMicroblog('sync');
+       else
+               waitMicroblog('unsync');
+       
+       return false;
+}
+
+// Gets the user's microblog to check it exists
+function getInitMicroblog() {
+       getMicroblog(getXID(), hex_md5(getXID()), true);
+}
+
+// Handles the user's microblog to create it in case of error
+function handleInitMicroblog(iq) {
+       // Any error?
+       if((iq.getType() == 'error') && $(iq.getNode()).find('item-not-found').size()) {
+               // The node may not exist, create it!
+               setupMicroblog('', NS_URN_MBLOG, '1', '1000000', '', '', true);
+               
+               logThis('Error while getting microblog, trying to reconfigure the Pubsub node!', 2);
+       }
+}
+
+// Requests an user's microblog
+function requestMicroblog(xid, items, get_item, handler) {
+       // Ask the server the user's microblog 
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setTo(xid);
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var ps_items = pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB}));
+       
+       // Request a particular item?
+       if(get_item)
+               ps_items.appendChild(iq.buildNode('item', {'id': get_item, 'xmlns': NS_PUBSUB}));
+       else
+               ps_items.setAttribute('max_items', items);
+       
+       if(handler)
+               con.send(iq, handler);
+       else
+               con.send(iq, handleMicroblog);
+       
+       return false;
+}
+
+// Gets the microblog of an user
+function getMicroblog(xid, hash, check) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#subscriber-retrieve */
+       
+       logThis('Get the microblog: ' + xid, 3);
+       
+       // Fire the wait event
+       waitMicroblog('fetch');
+       
+       // XMPP URI?
+       var get_item = '';
+       
+       if(xid.match(/^xmpp:(.+)\?;node=(.+);item=(.+)/)) {
+               xid = RegExp.$1;
+               get_item = decodeURIComponent(RegExp.$3);
+       }
+       
+       // No hash?
+       if(!hash)
+               hash = hex_md5(xid);
+       
+       // Can display the individual channel?
+       if(!check && !exists('#channel .individual')) {
+               // Hide the mixed channel
+               $('#channel .mixed').hide();
+               
+               // Get the channel title depending on the XID
+               var cTitle;
+               var cShortcuts = '';
+               
+               if(xid == getXID())
+                       cTitle = _e("Your channel");
+               else {
+                       cTitle = _e("Channel of") + ' ' + getBuddyName(xid).htmlEnc();
+                       cShortcuts = '<div class="shortcuts">' + 
+                                               '<a href="#" class="message talk-images" title="' + _e("Send him/her a message") + '" onclick="return composeInboxMessage(\'' + encodeOnclick(xid) + '\');"></a>' + 
+                                               '<a href="#" class="chat talk-images" title="' + _e("Start a chat with him/her") + '" onclick="return checkChatCreate(\'' + encodeOnclick(xid) + '\', \'chat\');"></a>' + 
+                                               '<a href="#" class="command talk-images" title="' + _e("Command") + '" onclick="return retrieveAdHoc(\'' + encodeOnclick(xid) + '\');"></a>' + 
+                                               '<a href="#" class="profile talk-images" title="' + _e("Show user profile") + '" onclick="return openUserInfos(\'' + encodeOnclick(xid) + '\');"></a>' + 
+                                    '</div>';
+               }
+               
+               // Create a new individual channel
+               $('#channel .content.mixed').after(
+                               '<div class="content individual microblog-' + hash + '">' + 
+                                       '<a href="#" class="more home-images" onclick="return getMicroblog(\'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(hash) + '\');">' + _e("More notices...") + '</a>' + 
+                               '</div>'
+                                                )
+                                          
+                                          .before(
+                               '<div class="top individual ' + hash + '">' + 
+                                       '<div class="avatar-container">' + 
+                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="update">' + 
+                                               '<h2>' + cTitle + '</h2>' + 
+                                               '<a href="#" onclick="return resetMicroblog();">« ' + _e("Previous") + '</a>' + 
+                                       '</div>' + 
+                                       
+                                       cShortcuts + 
+                                       
+                                       '<input type="hidden" name="jid" value="' + encodeQuotes(xid) + '" />' + 
+                                       '<input type="hidden" name="counter" value="20" />' + 
+                               '</div>'
+                                                );
+               
+               // Display the user avatar
+               getAvatar(xid, 'cache', 'true', 'forget');
+       }
+       
+       // Get the number of items to retrieve
+       var items = '0';
+       
+       if(!check)
+               items = $('#channel .top.individual input[name=counter]').val();
+       
+       // Request
+       if(check)
+               requestMicroblog(xid, items, get_item, handleInitMicroblog);
+       else
+               requestMicroblog(xid, items, get_item, handleMicroblog);
+       
+       return false;
+}
+
+// Show a given microblog waiting status
+function waitMicroblog(type) {
+       // First hide all the infos elements
+       $('#channel .footer div').hide();
+       
+       // Display the good one
+       $('#channel .footer div.' + type).show();
+       
+       // Depending on the type, disable/enable certain tools
+       var selector = $('#channel .top input[name=microblog_body]');
+       
+       if(type == 'unsync')
+               selector.attr('disabled', true);
+       else if(type == 'sync')
+               $(document).oneTime(10, function() {
+                       selector.removeAttr('disabled').focus();
+               });
+}
+
+// Setups a new microblog
+function setupMicroblog(entity, node, persist, maximum, access, publish, create) {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#owner-create-and-configure */
+       
+       // Create the PubSub node
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // Any external entity?
+       if(entity)
+               iq.setTo(entity);
+       
+       // Create it?
+       if(create) {
+               var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+               pubsub.appendChild(iq.buildNode('create', {'xmlns': NS_PUBSUB, 'node': node}));
+       }
+       
+       else
+               var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
+       
+       // Configure it!
+       var configure = pubsub.appendChild(iq.buildNode('configure', {'node': node, 'xmlns': NS_PUBSUB}));
+       var x = configure.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': 'submit'}));
+       
+       var field1 = x.appendChild(iq.buildNode('field', {'var': 'FORM_TYPE', 'type': 'hidden', 'xmlns': NS_XDATA}));
+       field1.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, NS_PUBSUB_NC));
+       
+       // Persist items?
+       if(persist) {
+               var field2 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#persist_items', 'xmlns': NS_XDATA}));
+               field2.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, persist));
+       }
+       
+       // Maximum items?
+       if(maximum) {
+               var field3 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#max_items', 'xmlns': NS_XDATA}));
+               field3.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, maximum));
+       }
+       
+       // Access rights?
+       if(access) {
+               var field4 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#access_model', 'xmlns': NS_XDATA}));
+               field4.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, access));
+       }
+       
+       // Publish rights?
+       if(publish) {
+               var field5 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#publish_model', 'xmlns': NS_XDATA}));
+               field5.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, publish));
+       }
+       
+       con.send(iq);
+}
+
+// Gets the microblog configuration
+function getConfigMicroblog() {
+       // Lock the microblog options
+       $('#persistent, #maxnotices').attr('disabled', true);
+       
+       // Get the microblog configuration
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
+       pubsub.appendChild(iq.buildNode('configure', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB_OWNER}));
+       
+       con.send(iq, handleGetConfigMicroblog);
+}
+
+// Handles the microblog configuration
+function handleGetConfigMicroblog(iq) {
+       // Reset the options stuffs
+       waitOptions('microblog');
+       
+       // Unlock the microblog options
+       $('#persistent, #maxnotices').removeAttr('disabled');
+       
+       // End if not a result
+       if(!iq || (iq.getType() != 'result'))
+               return;
+       
+       // Initialize the values
+       var selector = $(iq.getNode());
+       var persistent = '0';
+       var maxnotices = '1000000';
+       
+       // Get the values
+       var xPersistent = selector.find('field[var=pubsub#persist_items] value:first').text();
+       var xMaxnotices = selector.find('field[var=pubsub#max_items] value:first').text();
+       
+       // Any value?
+       if(xPersistent)
+               persistent = xPersistent;
+       
+       if(xMaxnotices)
+               maxnotices = xMaxnotices;
+       
+       // Change the maxnotices value
+       switch(maxnotices) {
+               case '1':
+               case '100':
+               case '1000':
+               case '10000':
+               case '100000':
+               case '1000000':
+                       break;
+               
+               default:
+                       maxnotices = '1000000';
+                       break;
+       }
+       
+       // Apply persistent value
+       if(persistent == '0')
+               $('#persistent').attr('checked', false);
+       else
+               $('#persistent').attr('checked', true);
+       
+       // Apply maxnotices value
+       $('#maxnotices').val(maxnotices);
+}
+
+// Handles the user's microblog
+function handleMyMicroblog(packet) {
+       // Reset the entire form
+       $('#channel .top input[name=microblog_body]').removeAttr('disabled').val('');
+       $('#channel .top input[name=microblog_body]').placeholder();
+       unattachMicroblog();
+       
+       // Check for errors
+       handleErrorReply(packet);
+}
+
+// Performs the microblog sender checks
+function sendMicroblog() {
+       logThis('Send a new microblog item', 3);
+       
+       // Avoid nasty errors
+       try {
+               // Get the values
+               var selector = $('#channel .top input[name=microblog_body]');
+               var body = trim(selector.val());
+               
+               // Sufficient parameters
+               if(body) {
+                       // Disable & blur our input
+                       selector.attr('disabled', true).blur();
+                       
+                       // Files array
+                       var fName = [];
+                       var fType = [];
+                       var fLength = [];
+                       var fURL = [];
+                       var fThumb = [];
+                       
+                       // Read the files
+                       $('#attach .one-file').each(function() {
+                               // Push the values!
+                               fName.push($(this).find('a.link').text());
+                               fType.push($(this).attr('data-type'));
+                               fLength.push($(this).attr('data-length'));
+                               fURL.push($(this).find('a.link').attr('href'));
+                               fThumb.push($(this).attr('data-thumb'));
+                       });
+                       
+                       // Containing YouTube videos?
+                       var yt_matches = body.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim);
+                       
+                       for(y in yt_matches) {
+                               fName.push('');
+                               fType.push('text/html');
+                               fLength.push('');
+                               fURL.push(trim(yt_matches[y]));
+                               fThumb.push('https://img.youtube.com/vi/' + trim(yt_matches[y].replace(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim, '$8')) + '/0.jpg');
+                       }
+                       
+                       // Send the message on the XMPP network
+                       publishMicroblog(body, fName, fURL, fType, fLength, fThumb);
+               }
+       }
+       
+       // Return false (security)
+       finally {
+               return false;
+       }
+}
+
+// Publishes a given microblog item
+function publishMicroblog(body, attachedname, attachedurl, attachedtype, attachedlength, attachedthumb, repeat, comments_entity, comments_node, comments_entity_file, comments_node_file) {
+       /* REF: http://xmpp.org/extensions/xep-0277.html */
+       
+       // Generate some values
+       var time = getXMPPTime('utc');
+       var id = hex_md5(body + time);
+       var nick = getName();
+       var xid = getXID();
+       
+       // Define repeat options
+       var author_nick = nick;
+       var author_xid = xid;
+       
+       if(repeat && repeat.length) {
+               author_nick = repeat[0];
+               author_xid = repeat[1];
+       }
+       
+       // Define comments options
+       var node_create = false;
+       
+       if(!comments_entity || !comments_node) {
+               node_create = true;
+               comments_entity = HOST_PUBSUB;
+               comments_node = NS_URN_MBLOG + ':comments/' + id;
+       }
+       
+       if(!comments_entity_file)
+               comments_entity_file = [];
+       if(!comments_node_file)
+               comments_node_file = [];
+       
+       // Don't create another comments node if only 1 file is attached
+       if(attachedurl && (attachedurl.length == 1) && (!comments_entity_file[0] || !comments_node_file[0])) {
+               comments_entity_file = [comments_entity];
+               comments_node_file = [comments_node];
+       }
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       iq.setTo(xid);
+       
+       // Create the main XML nodes/childs
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+       var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
+       
+       // Create the XML source childs
+       var Source = entry.appendChild(iq.buildNode('source', {'xmlns': NS_ATOM}));
+       var author = Source.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
+       author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, author_nick));
+       author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + author_xid));
+       
+       // Create the XML entry childs
+       entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, body));
+       entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, time));
+       entry.appendChild(iq.buildNode('updated', {'xmlns': NS_ATOM}, time));
+       entry.appendChild(iq.buildNode('link', {
+                       'rel': 'alternate',
+                       'href': 'xmpp:' + xid + '?;node=' + encodeURIComponent(NS_URN_MBLOG) + ';item=' + encodeURIComponent(id),
+                       'xmlns': NS_ATOM
+       }));
+       
+       // Create the attached files nodes
+       for(var i = 0; i < attachedurl.length; i++) {
+               // Not enough data?
+               if(!attachedurl[i])
+                       continue;
+               
+               // Append a new file element
+               var file = entry.appendChild(iq.buildNode('link', {'xmlns': NS_ATOM, 'rel': 'enclosure', 'href': attachedurl[i]}));
+               
+               // Add attributes
+               if(attachedname[i])
+                       file.setAttribute('title', attachedname[i]);
+               if(attachedtype[i])
+                       file.setAttribute('type', attachedtype[i]);
+               if(attachedlength[i])
+                       file.setAttribute('length', attachedlength[i]);
+               
+               // Any thumbnail?
+               if(attachedthumb[i])
+                       file.appendChild(iq.buildNode('link', {'xmlns': NS_URN_MBLOG, 'rel': 'self', 'title': 'thumb', 'type': attachedtype[i], 'href': attachedthumb[i]}));
+               
+               // Any comments node?
+               if(!comments_entity_file[i] || !comments_node_file[i]) {
+                       // Generate values
+                       comments_entity_file[i] = HOST_PUBSUB;
+                       comments_node_file[i] = NS_URN_MBLOG + ':comments/' + hex_md5(attachedurl[i] + attachedname[i] + attachedtype[i] + attachedlength[i] + time);
+                       
+                       // Create the node
+                       setupMicroblog(comments_entity_file[i], comments_node_file[i], '1', '1000000', 'open', 'open', true);
+               }
+               
+               file.appendChild(iq.buildNode('link', {'xmlns': NS_URN_MBLOG, 'rel': 'replies', 'title': 'comments_file', 'href': 'xmpp:' + comments_entity_file[i] + '?;node=' + encodeURIComponent(comments_node_file[i])}));
+       }
+       
+       // Create the comments child
+       entry.appendChild(iq.buildNode('link', {'xmlns': NS_ATOM, 'rel': 'replies', 'title': 'comments', 'href': 'xmpp:' + comments_entity + '?;node=' + encodeURIComponent(comments_node)}));
+       
+       // Create the geoloc child
+       var geoloc_xml = getDB('geolocation', 'now');
+       
+       if(geoloc_xml) {
+               // Create two position arrays
+               var geo_names  = ['lat', 'lon', 'country', 'countrycode', 'region', 'postalcode', 'locality', 'street', 'building', 'text', 'uri', 'timestamp'];
+               var geo_values = parsePosition(XMLFromString(geoloc_xml));
+               
+               // New geoloc child
+               var geoloc = entry.appendChild(iq.buildNode('geoloc', {'xmlns': NS_GEOLOC}));
+               
+               // Append the geoloc content
+               for(var g = 0; g < geo_names.length; g++) {
+                       if(geo_names[g] && geo_values[g])
+                               geoloc.appendChild(iq.buildNode(geo_names[g], {'xmlns': NS_GEOLOC}, geo_values[g]));
+               }
+       }
+       
+       // Send the IQ
+       con.send(iq, handleMyMicroblog);
+       
+       // Create the XML comments PubSub nodes
+       if(node_create)
+               setupMicroblog(comments_entity, comments_node, '1', '1000000', 'open', 'open', true);
+       
+       return false;
+}
+
+// Attaches a file to a microblog post
+function attachMicroblog() {
+       // File upload vars
+       var attach_options = {
+               dataType:       'xml',
+               beforeSubmit:   waitMicroblogAttach,
+               success:        handleMicroblogAttach
+       };
+       
+       // Upload form submit event
+       $('#attach').submit(function() {
+               if(!exists('#attach .wait') && $('#attach input[type=file]').val())
+                       $(this).ajaxSubmit(attach_options);
+               
+               return false;
+       });
+       
+       // Upload input change event
+       $('#attach input[type=file]').change(function() {
+               if(!exists('#attach .wait') && $(this).val())
+                       $('#attach').ajaxSubmit(attach_options);
+               
+               return false;
+       });
+}
+
+// Unattaches a microblog file
+function unattachMicroblog(id) {
+       // Individual removal?
+       if(id)
+               $('#attach .one-file[data-id=' + id + ']').remove();
+       else
+               $('#attach .one-file').remove();
+       
+       // Must enable the popup again?
+       if(!exists('#attach .one-file')) {
+               // Restore the bubble class
+               $('#attach').addClass('bubble');
+               
+               // Enable the bubble click events
+               if(id) {
+                       $('#attach').hide();
+                       showBubble('#attach');
+               }
+               
+               else
+                       closeBubbles();
+       }
+       
+       return false;
+}
+
+// Wait event for file attaching
+function waitMicroblogAttach() {
+       // Append the wait icon
+       $('#attach input[type=submit]').after('<div class="wait wait-medium"></div>');
+       
+       // Lock the bubble
+       $('#attach').removeClass('bubble');
+}
+
+// Success event for file attaching
+function handleMicroblogAttach(responseXML) {
+       // Data selector
+       var dData = $(responseXML).find('jappix');
+       
+       // Process the returned data
+       if(!dData.find('error').size()) {
+               // Do not allow this bubble to be hidden
+               $('#attach').removeClass('bubble');
+               
+               // Get the file values
+               var fName = dData.find('title').text();
+               var fType = dData.find('type').text();
+               var fLength = dData.find('length').text();
+               var fURL = dData.find('href').text();
+               var fThumb = dData.find('thumb').text();
+               
+               // Generate a file ID
+               var fID = hex_md5(fURL);
+               
+               // Add this file
+               $('#attach .attach-subitem').append(
+                       '<div class="one-file" data-type="' + encodeQuotes(fType) + '" data-length="' + encodeQuotes(fLength) + '" data-thumb="' + encodeQuotes(fThumb) + '" data-id="' + fID + '">' + 
+                               '<a class="remove talk-images" href="#" title="' + encodeQuotes(_e("Unattach the file")) + '"></a>' + 
+                               '<a class="link" href="' + encodeQuotes(fURL) + '" target="_blank">' + fName.htmlEnc() + '</a>' + 
+                       '</div>'
+               );
+               
+               // Click event
+               $('#attach .one-file[data-id=' + fID + '] a.remove').click(function() {
+                       return unattachMicroblog(fID);
+               });
+               
+               logThis('File attached.', 3);
+       }
+       
+       // Any error?
+       else {
+               openThisError(4);
+               
+               // Unlock the bubble?
+               if(!exists('#attach .one-file')) {
+                       $('#attach').addClass('bubble').hide();
+                       
+                       // Show the bubble again!
+                       showBubble('#attach');
+               }
+               
+               logThis('Error while attaching the file: ' + dData.find('error').text(), 1);
+       }
+       
+       // Reset the attach bubble
+       $('#attach input[type=file]').val('');
+       $('#attach .wait').remove();
+       
+       // Focus on the text input
+       $(document).oneTime(10, function() {
+               $('#channel .top input[name=microblog_body]').focus();
+       });
+}
+
+// Shows the microblog of an user from his infos
+function fromInfosMicroblog(xid, hash) {
+       // Renitialize the channel
+       resetMicroblog();
+       
+       // Switch to the channel
+       switchChan('channel');
+       
+       // Get the microblog
+       getMicroblog(xid, hash);
+}
+
+// Plugin launcher
+function launchMicroblog() {
+       // Keyboard event
+       $('#channel .top input[name=microblog_body]').keyup(function(e) {
+               // Enter pressed: send the microblog notice
+               if((e.keyCode == 13) && !exists('#attach .wait'))
+                       return sendMicroblog();
+       })
+       
+       // Placeholder
+       .placeholder();
+       
+       // Microblog file attacher
+       attachMicroblog();
+}
diff --git a/jappixmini/jappix/js/mini.js b/jappixmini/jappix/js/mini.js
new file mode 100644 (file)
index 0000000..0bfb808
--- /dev/null
@@ -0,0 +1,1623 @@
+/*
+
+Jappix - An open social platform
+These are the Jappix Mini JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 04/08/11
+
+*/
+
+// Jappix Mini vars
+var MINI_DISCONNECT    = false;
+var MINI_AUTOCONNECT   = false;
+var MINI_SHOWPANE      = false;
+var MINI_INITIALIZED   = false;
+var MINI_ANONYMOUS     = false;
+var MINI_ANIMATE       = false;
+var MINI_NICKNAME      = null;
+var MINI_TITLE         = null;
+var MINI_DOMAIN                = null;
+var MINI_USER          = null;
+var MINI_PASSWORD      = null;
+var MINI_RECONNECT     = 0;
+var MINI_GROUPCHATS    = [];
+var MINI_PASSWORDS     = [];
+var MINI_RESOURCE      = JAPPIX_RESOURCE + ' Mini';
+
+// Setups connection handlers
+function setupConMini(con) {
+       con.registerHandler('message', handleMessageMini);
+       con.registerHandler('presence', handlePresenceMini);
+       con.registerHandler('iq', handleIQMini);
+       con.registerHandler('onerror', handleErrorMini);
+       con.registerHandler('onconnect', connectedMini);
+}
+
+// Connects the user with the given logins
+function connectMini(domain, user, password) {
+       try {
+               // We define the http binding parameters
+               oArgs = new Object();
+               
+               if(HOST_BOSH_MINI)
+                       oArgs.httpbase = HOST_BOSH_MINI;
+               else
+                       oArgs.httpbase = HOST_BOSH;
+               
+               // We create the new http-binding connection
+               con = new JSJaCHttpBindingConnection(oArgs);
+               
+               // And we handle everything that happen
+               setupConMini(con);
+               
+               // Generate a resource
+               var random_resource = getDB('jappix-mini', 'resource');
+               
+               if(!random_resource)
+                       random_resource = MINI_RESOURCE + ' (' + (new Date()).getTime() + ')';
+               
+               // We retrieve what the user typed in the login inputs
+               oArgs = new Object();
+               oArgs.secure = true;
+               oArgs.xmllang = XML_LANG;
+               oArgs.resource = random_resource;
+               oArgs.domain = domain;
+               
+               // Store the resource (for reconnection)
+               setDB('jappix-mini', 'resource', random_resource);
+               
+               // Anonymous login?
+               if(MINI_ANONYMOUS) {
+                       // Anonymous mode disabled?
+                       if(!allowedAnonymous()) {
+                               logThis('Not allowed to use anonymous mode.', 2);
+                               
+                               // Notify this error
+                               notifyErrorMini();
+                               
+                               return false;
+                       }
+                       
+                       // Bad domain?
+                       else if(lockHost() && (domain != HOST_ANONYMOUS)) {
+                               logThis('Not allowed to connect to this anonymous domain: ' + domain, 2);
+                               
+                               // Notify this error
+                               notifyErrorMini();
+                               
+                               return false;
+                       }
+                       
+                       oArgs.authtype = 'saslanon';
+               }
+               
+               // Normal login
+               else {
+                       // Bad domain?
+                       if(lockHost() && (domain != HOST_MAIN)) {
+                               logThis('Not allowed to connect to this main domain: ' + domain, 2);
+                               
+                               // Notify this error
+                               notifyErrorMini();
+                               
+                               return false;
+                       }
+                       
+                       // No nickname?
+                       if(!MINI_NICKNAME)
+                               MINI_NICKNAME = user;
+                       
+                       oArgs.username = user;
+                       oArgs.pass = password;
+               }
+               
+               // We connect !
+               con.connect(oArgs);
+               
+               logThis('Jappix Mini is connecting...', 3);
+       }
+       
+       catch(e) {
+               // Logs errors
+               logThis('Error while logging in: ' + e, 1);
+               
+               // Reset Jappix Mini
+               disconnectedMini();
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+// When the user is connected
+function connectedMini() {
+       // Update the roster
+       jQuery('#jappix_mini a.jm_pane.jm_button span.jm_counter').text('0');
+       
+       // Do not get the roster if anonymous
+       if(MINI_ANONYMOUS)
+               initializeMini();
+       else
+               getRosterMini();
+       
+       // For logger
+       if(MINI_RECONNECT)
+               logThis('Jappix Mini is now reconnected.', 3);
+       else
+               logThis('Jappix Mini is now connected.', 3);
+       
+       // Reset reconnect var
+       MINI_RECONNECT = 0;
+}
+
+// When the user disconnects
+function saveSessionMini() {
+       // Not connected?
+       if(!isConnected())
+               return;
+       
+       // Save the actual Jappix Mini DOM
+       setDB('jappix-mini', 'dom', jQuery('#jappix_mini').html());
+       setDB('jappix-mini', 'nickname', MINI_NICKNAME);
+       
+       // Save the scrollbar position
+       var scroll_position = '';
+       var scroll_hash = jQuery('#jappix_mini div.jm_conversation:has(a.jm_pane.jm_clicked)').attr('data-hash');
+       
+       if(scroll_hash)
+               scroll_position = document.getElementById('received-' + scroll_hash).scrollTop + '';
+       
+       setDB('jappix-mini', 'scroll', scroll_position);
+       
+       // Save the session stamp
+       setDB('jappix-mini', 'stamp', getTimeStamp());
+       
+       // Suspend connection
+       con.suspend(false);
+       
+       logThis('Jappix Mini session save tool launched.', 3);
+}
+
+// Disconnects the connected user
+function disconnectMini() {
+       // No connection?
+       if(!isConnected())
+               return false;
+       
+       // Change markers
+       MINI_DISCONNECT = true;
+       MINI_INITIALIZED = false;
+       
+       // Add disconnection handler
+       con.registerHandler('ondisconnect', disconnectedMini);
+       
+       // Disconnect the user
+       con.disconnect();
+       
+       logThis('Jappix Mini is disconnecting...', 3);
+       
+       return false;
+}
+
+// When the user is disconnected
+function disconnectedMini() {
+       // Remove the stored items
+       removeDB('jappix-mini', 'dom');
+       removeDB('jappix-mini', 'nickname');
+       removeDB('jappix-mini', 'scroll');
+       removeDB('jappix-mini', 'stamp');
+       
+       // Connection error?
+       if(!MINI_DISCONNECT || MINI_INITIALIZED) {
+               // Browser error?
+               notifyErrorMini();
+               
+               // Reset reconnect timer
+               jQuery('#jappix_mini').stopTime();
+               
+               // Try to reconnect after a while
+               if(MINI_INITIALIZED && (MINI_RECONNECT < 5)) {
+                       // Reconnect interval
+                       var reconnect_interval = 10;
+                       
+                       if(MINI_RECONNECT)
+                               reconnect_interval = (5 + (5 * MINI_RECONNECT)) * 1000;
+                       
+                       MINI_RECONNECT++;
+                       
+                       // Set timer
+                       jQuery('#jappix_mini').oneTime(reconnect_interval, function() {
+                               launchMini(true, MINI_SHOWPANE, MINI_DOMAIN, MINI_USER, MINI_PASSWORD);
+                       });
+               }
+       }
+       
+       // Normal disconnection?
+       else
+               launchMini(false, MINI_SHOWPANE, MINI_DOMAIN, MINI_USER, MINI_PASSWORD);
+       
+       // Reset markers
+       MINI_DISCONNECT = false;
+       MINI_INITIALIZED = false;
+       
+       logThis('Jappix Mini is now disconnected.', 3);
+}
+
+// Handles the incoming messages
+function handleMessageMini(msg) {
+       var type = msg.getType();
+       
+       // This is a message Jappix can handle
+       if((type == 'chat') || (type == 'normal') || (type == 'groupchat') || !type) {
+               // Get the body
+               var body = trim(msg.getBody());
+               
+               // Any subject?
+               var subject = trim(msg.getSubject());
+               
+               if(subject)
+                       body = subject;
+               
+               if(body) {
+                       // Get the values
+                       var from = fullXID(getStanzaFrom(msg));
+                       var xid = bareXID(from);
+                       var use_xid = xid;
+                       var hash = hex_md5(xid);
+                       var nick = thisResource(from);
+                       
+                       // Read the delay
+                       var delay = readMessageDelay(msg.getNode());
+                       var d_stamp;
+                       
+                       // Manage this delay
+                       if(delay) {
+                               time = relativeDate(delay);
+                               d_stamp = Date.jab2date(delay);
+                       }
+                       
+                       else {
+                               time = getCompleteTime();
+                               d_stamp = new Date();
+                       }
+                       
+                       // Get the stamp
+                       var stamp = extractStamp(d_stamp);
+                       
+                       // Is this a groupchat private message?
+                       if(exists('#jappix_mini #chat-' + hash + '[data-type=groupchat]')) {
+                               // Regenerate some stuffs
+                               if((type == 'chat') || !type) {
+                                       xid = from;
+                                       hash = hex_md5(xid);
+                               }
+                               
+                               // XID to use for a groupchat
+                               else
+                                       use_xid = from;
+                       }
+                       
+                       // Message type
+                       var message_type = 'user-message';
+                       
+                       // Grouphat values
+                       if(type == 'groupchat') {
+                               // Old message
+                               if(msg.getChild('delay', NS_URN_DELAY) || msg.getChild('x', NS_DELAY))
+                                       message_type = 'old-message';
+                               
+                               // System message?
+                               if(!nick || subject) {
+                                       nick = '';
+                                       message_type = 'system-message';
+                               }
+                       }
+                       
+                       // Chat values
+                       else {
+                               nick = jQuery('#jappix_mini a#friend-' + hash).text().revertHtmlEnc();
+                               
+                               // No nickname?
+                               if(!nick)
+                                       nick = getXIDNick(xid);
+                       }
+                       
+                       // Define the target div
+                       var target = '#jappix_mini #chat-' + hash;
+                       
+                       // Create the chat if it does not exist
+                       if(!exists(target) && (type != 'groupchat'))
+                               chatMini(type, xid, nick, hash);
+                       
+                       // Display the message
+                       displayMessageMini(type, body, use_xid, nick, hash, time, stamp, message_type);
+                       
+                       // Notify the user if not focused & the message is not a groupchat old one
+                       if((!jQuery(target + ' a.jm_chat-tab').hasClass('jm_clicked') || !isFocused()) && (message_type == 'user-message'))
+                               notifyMessageMini(hash);
+                       
+                       logThis('Message received from: ' + from);
+               }
+       }
+}
+
+// Handles the incoming IQs
+function handleIQMini(iq) {
+       // Define some variables
+       var iqFrom = fullXID(getStanzaFrom(iq));
+       var iqID = iq.getID();
+       var iqQueryXMLNS = iq.getQueryXMLNS();
+       var iqType = iq.getType();
+       var iqNode = iq.getNode();
+       
+       // Build the response
+       var iqResponse = new JSJaCIQ();
+       
+       iqResponse.setID(iqID);
+       iqResponse.setTo(iqFrom);
+       iqResponse.setType('result');
+       
+       // Software version query
+       if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0092.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_VERSION);
+               
+               iqQuery.appendChild(iq.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix Mini'));
+               iqQuery.appendChild(iq.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
+               iqQuery.appendChild(iq.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
+               
+               con.send(iqResponse);
+               
+               logThis('Received software version query: ' + iqFrom);
+       }
+       
+       // Roster push
+       else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set')) {
+               // Display the friend
+               handleRosterMini(iq);
+               
+               con.send(iqResponse);
+               
+               logThis('Received a roster push.');
+       }
+       
+       // Disco info query
+       else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0030.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
+               
+               // We set the name of the client
+               iqQuery.appendChild(iq.appendNode('identity', {
+                       'category': 'client',
+                       'type': 'web',
+                       'name': 'Jappix Mini',
+                       'xmlns': NS_DISCO_INFO
+               }));
+               
+               // We set all the supported features
+               var fArray = new Array(
+                       NS_DISCO_INFO,
+                       NS_VERSION,
+                       NS_ROSTER,
+                       NS_MUC,
+                       NS_VERSION,
+                       NS_URN_TIME
+               );
+               
+               for(i in fArray)
+                       iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i], 'xmlns': NS_DISCO_INFO}));
+               
+               con.send(iqResponse);
+               
+               logThis('Received a disco#infos query.');
+       }
+       
+       // User time query
+       else if(jQuery(iqNode).find('time').size() && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0202.html */
+               
+               var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
+               iqTime.appendChild(iq.buildNode('tzo', {'xmlns': NS_URN_TIME}, getDateTZO()));
+               iqTime.appendChild(iq.buildNode('utc', {'xmlns': NS_URN_TIME}, getXMPPTime('utc')));
+               
+               con.send(iqResponse);
+               
+               logThis('Received local time query: ' + iqFrom);
+       }
+}
+
+// Handles the incoming errors
+function handleErrorMini(err) {
+       // First level error (connection error)
+       if(jQuery(err).is('error')) {
+               // Notify this error
+               disconnectedMini();
+               
+               logThis('First level error received.', 1);
+       }
+}
+
+// Handles the incoming presences
+function handlePresenceMini(pr) {
+       // Get the values
+       var from = fullXID(getStanzaFrom(pr));
+       var xid = bareXID(from);
+       var resource = thisResource(from);
+       var hash = hex_md5(xid);
+       var type = pr.getType();
+       var show = pr.getShow();
+       
+       // Manage the received presence values
+       if((type == 'error') || (type == 'unavailable'))
+               show = 'unavailable';
+       
+       else {
+               switch(show) {
+                       case 'chat':
+                       case 'away':
+                       case 'xa':
+                       case 'dnd':
+                               break;
+                       
+                       default:
+                               show = 'available';
+                               
+                               break;
+               }
+       }
+       
+       // Is this a groupchat presence?
+       var groupchat_path = '#jappix_mini #chat-' + hash + '[data-type=groupchat]';
+       
+       if(exists(groupchat_path)) {
+               // Groupchat buddy presence (not me)
+               if(resource != unescape(jQuery(groupchat_path).attr('data-nick'))) {
+                       // Regenerate some stuffs
+                       var groupchat = xid;
+                       xid = from;
+                       hash = hex_md5(xid);
+                       
+                       // Remove this from the roster
+                       if(show == 'unavailable')
+                               removeBuddyMini(hash, groupchat);
+                       
+                       // Add this to the roster
+                       else
+                               addBuddyMini(xid, hash, resource, groupchat);
+               }
+       }
+       
+       // Friend path
+       var chat = '#jappix_mini #chat-' + hash;
+       var friend = '#jappix_mini a#friend-' + hash;
+       var send_input = chat + ' input.jm_send-messages';
+       
+       // Is this friend online?
+       if(show == 'unavailable') {
+               // Offline marker
+               jQuery(friend).addClass('jm_offline').removeClass('jm_online');
+               
+               // Disable the chat tools
+               jQuery(chat).addClass('jm_disabled');
+               jQuery(send_input).attr('disabled', true).attr('data-value', _e("Unavailable")).val(_e("Unavailable"));
+       }
+       
+       else {
+               // Online marker
+               jQuery(friend).removeClass('jm_offline').addClass('jm_online');
+               
+               // Enable the chat input
+               jQuery(chat).removeClass('jm_disabled');
+               jQuery(send_input).removeAttr('disabled').val('');
+       }
+       
+       // Change the show presence of this buddy
+       jQuery(friend + ' span.jm_presence, ' + chat + ' span.jm_presence').attr('class', 'jm_presence jm_images jm_' + show);
+       
+       // Update the presence counter
+       updateRosterMini();
+       
+       logThis('Presence received from: ' + from);
+}
+
+// Handles the MUC main elements
+function handleMUCMini(pr) {
+       // We get the xml content
+       var xml = pr.getNode();
+       var from = fullXID(getStanzaFrom(pr));
+       var room = bareXID(from);
+       var hash = hex_md5(room);
+       var resource = thisResource(from);
+       
+       // Is it a valid server presence?
+       var valid = false;
+       
+       if(!resource || (resource == unescape(jQuery('#jappix_mini #chat-' + hash + '[data-type=groupchat]').attr('data-nick'))))
+               valid = true;
+       
+       // Password required?
+       if(valid && jQuery(xml).find('error[type=auth] not-authorized').size()) {
+               // Create a new prompt
+               openPromptMini(printf(_e("This room (%s) is protected with a password."), room));
+               
+               // When prompt submitted
+               jQuery('#jappix_popup div.jm_prompt form').submit(function() {
+                       try {
+                               // Read the value
+                               var password = closePromptMini();
+                               
+                               // Any submitted chat to join?
+                               if(password) {
+                                       // Send the password
+                                       presenceMini('', '', '', '', from, password, true, handleMUCMini);
+                                       
+                                       // Focus on the pane again
+                                       switchPaneMini('chat-' + hash, hash);
+                               }
+                       }
+                       
+                       catch(e) {}
+                       
+                       finally {
+                               return false;
+                       }
+               });
+               
+               return;
+       }
+       
+       // Nickname conflict?
+       else if(valid && jQuery(xml).find('error[type=cancel] conflict').size()) {
+               // New nickname
+               var nickname = resource + '_';
+               
+               // Send the new presence
+               presenceMini('', '', '', '', room + '/' + nickname, '', true, handleMUCMini);
+               
+               // Update the nickname marker
+               jQuery('#jappix_mini #chat-' + hash).attr('data-nick', escape(nickname));
+       }
+       
+       // Handle normal presence
+       else
+               handlePresenceMini(pr);
+}
+
+// Updates the user presence
+function presenceMini(type, show, priority, status, to, password, limit_history, handler) {
+       var pr = new JSJaCPresence();
+       
+       // Add the attributes
+       if(to)
+               pr.setTo(to);
+       if(type)
+               pr.setType(type);
+       if(show)
+               pr.setShow(show);
+       if(priority)
+               pr.setPriority(priority);
+       if(status)
+               pr.setStatus(status);
+       
+       // Special presence elements
+       if(password || limit_history) {
+               var x = pr.appendNode('x', {'xmlns': NS_MUC});
+               
+               // Any password?
+               if(password)
+                       x.appendChild(pr.buildNode('password', {'xmlns': NS_MUC}, password));
+               
+               // Any history limit?
+               if(limit_history)
+                       x.appendChild(pr.buildNode('history', {'maxstanzas': 10, 'seconds': 86400, 'xmlns': NS_MUC}));
+       }
+       
+       // Send the packet
+       if(handler)
+               con.send(pr, handler);
+       else
+               con.send(pr);
+       
+       // No type?
+       if(!type)
+               type = 'available';
+       
+       logThis('Presence sent: ' + type, 3);
+}
+
+// Sends a given message
+function sendMessageMini(aForm) {
+       try {
+               var body = trim(aForm.body.value);
+               var xid = aForm.xid.value;
+               var type = aForm.type.value;
+               var hash = hex_md5(xid);
+               
+               if(body && xid) {
+                       // Send the message
+                       var aMsg = new JSJaCMessage();
+                       
+                       aMsg.setTo(xid);
+                       aMsg.setType(type);
+                       aMsg.setBody(body);
+                       
+                       con.send(aMsg);
+                       
+                       // Clear the input
+                       aForm.body.value = '';
+                       
+                       // Display the message we sent
+                       if(type != 'groupchat')
+                               displayMessageMini(type, body, getXID(), 'me', hash, getCompleteTime(), getTimeStamp(), 'user-message');
+                       
+                       logThis('Message (' + type + ') sent to: ' + xid);
+               }
+       }
+       
+       catch(e) {}
+       
+       finally {
+               return false;
+       }
+}
+
+// Generates the asked smiley image
+function smileyMini(image, text) {
+       return ' <img class="jm_smiley jm_smiley-' + image + ' jm_images" alt="' + encodeQuotes(text) + '" src="' + JAPPIX_STATIC + 'php/get.php?t=img&amp;f=others/blank.gif" /> ';
+}
+
+// Notifies incoming chat messages
+function notifyMessageMini(hash) {
+       // Define the paths
+       var tab = '#jappix_mini #chat-' + hash + ' a.jm_chat-tab';
+       var notify = tab + ' span.jm_notify';
+       var notify_middle = notify + ' span.jm_notify_middle';
+       
+       // Notification box not yet added
+       if(!exists(notify))
+               jQuery(tab).append(
+                       '<span class="jm_notify">' + 
+                               '<span class="jm_notify_left jm_images"></span>' + 
+                               '<span class="jm_notify_middle">0</span>' + 
+                               '<span class="jm_notify_right jm_images"></span>' + 
+                       '</span>'
+               );
+       
+       // Increment the notification number
+       var number = parseInt(jQuery(notify_middle).text());
+       jQuery(notify_middle).text(number + 1);
+       
+       // Change the page title
+       notifyTitleMini();
+}
+
+// Notifies the user from a session error
+function notifyErrorMini() {
+       // Replace the Jappix Mini DOM content
+       jQuery('#jappix_mini').html(
+               '<div class="jm_starter">' + 
+                       '<a class="jm_pane jm_button jm_images" href="https://mini.jappix.com/issues" target="_blank" title="' + _e("Click here to solve the error") + '">' + 
+                               '<span class="jm_counter jm_error jm_images">' + _e("Error") + '</span>' + 
+                       '</a>' + 
+               '</div>'
+       );
+}
+
+// Updates the page title with the new notifications
+function notifyTitleMini() {
+       // No saved title? Abort!
+       if(MINI_TITLE == null)
+               return false;
+       
+       // Page title code
+       var title = MINI_TITLE;
+       
+       // Count the number of notifications
+       var number = 0;
+       
+       jQuery('#jappix_mini span.jm_notify span.jm_notify_middle').each(function() {
+               number = number + parseInt(jQuery(this).text());
+       });
+       
+       // No new stuffs? Reset the title!
+       if(number)
+               title = '[' + number + '] ' + title;
+       
+       // Apply the title
+       document.title = title;
+       
+       return true;
+}
+
+// Clears the notifications
+function clearNotificationsMini(hash) {
+       // Not focused?
+       if(!isFocused())
+               return false;
+       
+       // Remove the notifications counter
+       jQuery('#jappix_mini #chat-' + hash + ' span.jm_notify').remove();
+       
+       // Update the page title
+       notifyTitleMini();
+       
+       return true;
+}
+
+// Updates the roster counter
+function updateRosterMini() {
+       jQuery('#jappix_mini a.jm_button span.jm_counter').text(jQuery('#jappix_mini a.jm_online').size());
+}
+
+// Creates the Jappix Mini DOM content
+function createMini(domain, user, password) {
+       // Try to restore the DOM
+        var dom = getDB('jappix-mini', 'dom');
+        var stamp = parseInt(getDB('jappix-mini', 'stamp'));
+       var suspended = false;
+       
+       // Invalid stored DOM?
+       if(dom && isNaN(jQuery(dom).find('a.jm_pane.jm_button span.jm_counter').text()))
+               dom = null;
+       
+       // Can resume a session?
+       con = new JSJaCHttpBindingConnection();
+       setupConMini(con);
+       
+       // Old DOM?
+       if(dom && ((getTimeStamp() - stamp) < JSJACHBC_MAX_WAIT) && con.resume()) {
+               // Read the old nickname
+               MINI_NICKNAME = getDB('jappix-mini', 'nickname');
+               
+               // Marker
+               suspended = true;
+       }
+       
+       // New DOM?
+       else {
+               dom =   '<div class="jm_position">' + 
+                               '<div class="jm_conversations"></div>' + 
+                               
+                               '<div class="jm_starter">' + 
+                                       '<div class="jm_roster">' + 
+                                               '<div class="jm_actions">' + 
+                                                       '<a class="jm_logo jm_images" href="https://mini.jappix.com/" target="_blank"></a>' + 
+                                                       '<a class="jm_one-action jm_join jm_images" title="' + _e("Join a chat") + '" href="#"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="jm_buddies"></div>' + 
+                                       '</div>' + 
+                                       
+                                       '<a class="jm_pane jm_button jm_images" href="#">' + 
+                                               '<span class="jm_counter jm_images">' + _e("Please wait...") + '</span>' + 
+                                       '</a>' + 
+                               '</div>' + 
+                       '</div>';
+       }
+       
+       // Create the DOM
+       jQuery('body').append('<div id="jappix_mini">' + dom + '</div>');
+       
+       // Adapt roster height
+       adaptRosterMini();
+       
+       // The click events
+       jQuery('#jappix_mini a.jm_button').click(function() {
+               // Using a try/catch override IE issues
+               try {
+                       // Presence counter
+                       var counter = '#jappix_mini a.jm_pane.jm_button span.jm_counter';
+                       
+                       // Cannot open the roster?
+                       if(jQuery(counter).text() == _e("Please wait..."))
+                               return false;
+                       
+                       // Not yet connected?
+                       if(jQuery(counter).text() == _e("Chat")) {
+                               // Remove the animated bubble
+                               jQuery('#jappix_mini div.jm_starter span.jm_animate').stopTime().remove();
+                               
+                               // Add a waiting marker
+                               jQuery(counter).text(_e("Please wait..."));
+                               
+                               // Launch the connection!
+                               connectMini(domain, user, password);
+                               
+                               return false;
+                       }
+                       
+                       // Normal actions
+                       if(!jQuery(this).hasClass('jm_clicked'))
+                               showRosterMini();
+                       else
+                               hideRosterMini();
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+       
+       jQuery('#jappix_mini div.jm_actions a.jm_join').click(function() {
+               // Using a try/catch override IE issues
+               try {
+                       // Create a new prompt
+                       openPromptMini(_e("Please enter the group chat address to join."));
+                       
+                       // When prompt submitted
+                       jQuery('#jappix_popup div.jm_prompt form').submit(function() {
+                               try {
+                                       // Read the value
+                                       var join_this = closePromptMini();
+                                       
+                                       // Any submitted chat to join?
+                                       if(join_this) {
+                                               // Get the chat room to join
+                                               chat_room = bareXID(generateXID(join_this, 'groupchat'));
+                                               
+                                               // Create a new groupchat
+                                               chatMini('groupchat', chat_room, getXIDNick(chat_room), hex_md5(chat_room));
+                                       }
+                               }
+                               
+                               catch(e) {}
+                               
+                               finally {
+                                       return false;
+                               }
+                       });
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+       
+       // Hides the roster when clicking away of Jappix Mini
+       jQuery(document).click(function(evt) {
+               if(!jQuery(evt.target).parents('#jappix_mini').size() && !exists('#jappix_popup'))
+                       hideRosterMini();
+       });
+       
+       // Hides all panes double clicking away of Jappix Mini
+       jQuery(document).dblclick(function(evt) {
+               if(!jQuery(evt.target).parents('#jappix_mini').size() && !exists('#jappix_popup'))
+                       switchPaneMini();
+       });
+       
+       // Suspended session resumed?
+       if(suspended) {
+               // Initialized marker
+               MINI_INITIALIZED = true;
+               
+               // Restore chat input values
+               jQuery('#jappix_mini div.jm_conversation input.jm_send-messages').each(function() {
+                       var chat_value = jQuery(this).attr('data-value');
+                       
+                       if(chat_value)
+                               jQuery(this).val(chat_value);
+               });
+               
+               // Restore buddy click events
+               jQuery('#jappix_mini a.jm_friend').click(function() {
+                       // Using a try/catch override IE issues
+                       try {
+                               chatMini('chat', unescape(jQuery(this).attr('data-xid')), unescape(jQuery(this).attr('data-nick')), jQuery(this).attr('data-hash'));
+                       }
+                       
+                       catch(e) {}
+                       
+                       finally {
+                               return false;
+                       }
+               });
+               
+               // Restore chat click events
+               jQuery('#jappix_mini div.jm_conversation').each(function() {
+                       chatEventsMini(jQuery(this).attr('data-type'), unescape(jQuery(this).attr('data-xid')), jQuery(this).attr('data-hash'));
+               });
+               
+               // Scroll down to the last message
+               var scroll_hash = jQuery('#jappix_mini div.jm_conversation:has(a.jm_pane.jm_clicked)').attr('data-hash');
+               var scroll_position = getDB('jappix-mini', 'scroll');
+               
+               // Any scroll position?
+               if(scroll_position)
+                       scroll_position = parseInt(scroll_position);
+               
+               if(scroll_hash) {
+                       // Use a timer to override the DOM lag issue
+                       jQuery(document).oneTime(200, function() {
+                               messageScrollMini(scroll_hash, scroll_position);
+                       });
+               }
+               
+               // Update title notifications
+               notifyTitleMini();
+       }
+       
+       // Can auto-connect?
+       else if(MINI_AUTOCONNECT)
+               connectMini(domain, user, password);
+       
+       // Cannot auto-connect?
+       else {
+               // Chat text
+               jQuery('#jappix_mini a.jm_pane.jm_button span.jm_counter').text(_e("Chat"));
+               
+               // Must animate?
+               if(MINI_ANIMATE) {
+                       // Add content
+                       jQuery('#jappix_mini div.jm_starter').prepend(
+                               '<span class="jm_animate jm_images_animate"></span>'
+                       );
+                       
+                       // IE6 makes the image blink when animated...
+                       if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 7))
+                               return;
+                       
+                       // Add timers
+                       var anim_i = 0;
+                       
+                       jQuery('#jappix_mini div.jm_starter span.jm_animate').everyTime(10, function() {
+                               // Next
+                               anim_i++;
+                               
+                               // Margins
+                               var m_top = Math.cos(anim_i * 0.02) * 3;
+                               var m_left = Math.sin(anim_i * 0.02) * 3;
+                               
+                               // Apply new position!
+                               jQuery(this).css('margin-top', m_top + 'px')
+                                           .css('margin-left', m_left + 'px');
+                       });
+               }
+       }
+}
+
+// Displays a given message
+function displayMessageMini(type, body, xid, nick, hash, time, stamp, message_type) {
+       // Generate path
+       var path = '#chat-' + hash;
+       
+       // Can scroll?
+       var cont_scroll = document.getElementById('received-' + hash);
+       var can_scroll = false;
+       
+       if(!cont_scroll.scrollTop || ((cont_scroll.clientHeight + cont_scroll.scrollTop) == cont_scroll.scrollHeight))
+               can_scroll = true;
+       
+       // Remove the previous message border if needed
+       var last = jQuery(path + ' div.jm_group:last');
+       var last_stamp = parseInt(last.attr('data-stamp'));
+       var last_b = jQuery(path + ' b:last');
+       var last_xid = last_b.attr('data-xid');
+       var last_type = last.attr('data-type');
+       var grouped = false;
+       var header = '';
+       
+       if((last_xid == xid) && (message_type == last_type) && ((stamp - last_stamp) <= 1800))
+               grouped = true;
+       
+       else {
+               // Write the message date
+               if(nick)
+                       header += '<span class="jm_date">' + time + '</span>';
+               
+               // Write the buddy name at the top of the message group
+               if(type == 'groupchat')
+                       header += '<b style="color: ' + generateColor(nick) + ';" data-xid="' + encodeQuotes(xid) + '">' + nick.htmlEnc() + '</b>';
+               else if(nick == 'me')
+                       header += '<b class="jm_me" data-xid="' + encodeQuotes(xid) + '">' + _e("You") + '</b>';
+               else
+                       header += '<b class="jm_him" data-xid="' + encodeQuotes(xid) + '">' + nick.htmlEnc() + '</b>';
+       }
+       
+       // Apply the /me command
+       var me_command = false;
+       
+       if(body.match(/^\/me /i)) {
+               body = body.replace(/^\/me /i, nick + ' ');
+               
+               // Marker
+               me_command = true;
+       }
+       
+       // HTML-encode the message
+       body = body.htmlEnc();
+       
+       // Apply the smileys
+       body = body.replace(/(;-?\))(\s|$)/gi, smileyMini('wink', '$1'))
+                  .replace(/(:-?3)(\s|$)/gi, smileyMini('waii', '$1'))
+                  .replace(/(:-?\()(\s|$)/gi, smileyMini('unhappy', '$1'))
+                  .replace(/(:-?P)(\s|$)/gi, smileyMini('tongue', '$1'))
+                  .replace(/(:-?O)(\s|$)/gi, smileyMini('surprised', '$1'))
+                  .replace(/(:-?\))(\s|$)/gi, smileyMini('smile', '$1'))
+                  .replace(/(\^_?\^)(\s|$)/gi, smileyMini('happy', '$1'))
+                  .replace(/(:-?D)(\s|$)/gi, smileyMini('grin', '$1'));
+       
+       // Filter the links
+       body = applyLinks(body, 'mini');
+       
+       // Generate the message code
+       if(me_command)
+               body = '<em>' + body + '</em>';
+       
+       body = '<p>' + body + '</p>';
+       
+       // Create the message
+       if(grouped)
+               jQuery('#jappix_mini #chat-' + hash + ' div.jm_received-messages div.jm_group:last').append(body);
+       else
+               jQuery('#jappix_mini #chat-' + hash + ' div.jm_received-messages').append('<div class="jm_group jm_' + message_type + '" data-type="' + message_type + '" data-stamp="' + stamp + '">' + header + body + '</div>');
+       
+       // Scroll to this message
+       if(can_scroll)
+               messageScrollMini(hash);
+}
+
+// Switches to a given point
+function switchPaneMini(element, hash) {
+       // Hide every item
+       jQuery('#jappix_mini a.jm_pane').removeClass('jm_clicked');
+       jQuery('#jappix_mini div.jm_roster, #jappix_mini div.jm_chat-content').hide();
+       
+       // Show the asked element
+       if(element && (element != 'roster')) {
+               var current = '#jappix_mini #' + element;
+               
+               jQuery(current + ' a.jm_pane').addClass('jm_clicked');
+               jQuery(current + ' div.jm_chat-content').show();
+               
+               // Use a timer to override the DOM lag issue
+               jQuery(document).oneTime(10, function() {
+                       jQuery(current + ' input.jm_send-messages').focus();
+               });
+               
+               // Scroll to the last message
+               if(hash)
+                       messageScrollMini(hash);
+       }
+}
+
+// Scrolls to the last chat message
+function messageScrollMini(hash, position) {
+       var id = document.getElementById('received-' + hash);
+       
+       // No defined position?
+       if(!position)
+               position = id.scrollHeight;
+       
+       id.scrollTop = position;
+}
+
+// Prompts the user with a given text
+function openPromptMini(text, value) {
+       // Initialize
+       var prompt = '#jappix_popup div.jm_prompt';
+       var input = prompt + ' form input';
+       var value_input = input + '[type=text]';
+       
+       // Remove the existing prompt
+       closePromptMini();
+       
+       // Add the prompt
+       jQuery('body').append(
+               '<div id="jappix_popup">' + 
+                       '<div class="jm_prompt">' + 
+                               '<form>' + 
+                                       text + 
+                                       '<input class="jm_text" type="text" value="" />' + 
+                                       '<input class="jm_submit" type="submit" value="' + _e("Submit") + '" />' + 
+                                       '<input class="jm_submit" type="reset" value="' + _e("Cancel") + '" />' + 
+                                       '<div class="jm_clear"></div>' + 
+                               '</form>' + 
+                       '</div>' + 
+               '</div>'
+       );
+       
+       // Vertical center
+       var vert_pos = '-' + ((jQuery(prompt).height() / 2) + 10) + 'px';
+       jQuery(prompt).css('margin-top', vert_pos);
+       
+       // Apply the value?
+       if(value)
+               jQuery(value_input).val(value);
+       
+       // Focus on the input
+       jQuery(document).oneTime(10, function() {
+               jQuery(value_input).focus();
+       });
+       
+       // Cancel event
+       jQuery(input + '[type=reset]').click(function() {
+               try {
+                       closePromptMini();
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+}
+
+// Returns the prompt value
+function closePromptMini() {
+       // Read the value
+       var value = jQuery('#jappix_popup div.jm_prompt form input').val();
+       
+       // Remove the popup
+       jQuery('#jappix_popup').remove();
+       
+       return value;
+}
+
+// Manages and creates a chat
+function chatMini(type, xid, nick, hash, pwd, show_pane) {
+       var current = '#jappix_mini #chat-' + hash;
+       
+       // Not yet added?
+       if(!exists(current)) {
+               // Groupchat nickname
+               if(type == 'groupchat') {
+                       var nickname = MINI_NICKNAME;
+                       
+                       // No nickname?
+                       if(!nickname) {
+                               // Create a new prompt
+                               openPromptMini(printf(_e("Please enter your nickname to join %s."), xid));
+                               
+                               // When prompt submitted
+                               jQuery('#jappix_popup div.jm_prompt form').submit(function() {
+                                       try {
+                                               // Read the value
+                                               var nickname = closePromptMini();
+                                               
+                                               // Update the stored one
+                                               if(nickname)
+                                                       MINI_NICKNAME = nickname;
+                                               
+                                               // Launch it again!
+                                               chatMini(type, xid, nick, hash, pwd);
+                                       }
+                                       
+                                       catch(e) {}
+                                       
+                                       finally {
+                                               return false;
+                                       }
+                               });
+                               
+                               return;
+                       }
+               }
+               
+               // Create the HTML markup
+               var html = '<div class="jm_conversation jm_type_' + type + '" id="chat-' + hash + '" data-xid="' + escape(xid) + '" data-type="' + type + '" data-nick="' + escape(nick) + '" data-hash="' + hash + '" data-origin="' + escape(cutResource(xid)) + '">' + 
+                               '<div class="jm_chat-content">' + 
+                                       '<div class="jm_actions">' + 
+                                               '<span class="jm_nick">' + nick + '</span>';
+               
+               // Check if the groupchat exists
+               var groupchat_exists = false;
+               
+               if(MINI_GROUPCHATS && MINI_GROUPCHATS.length) {
+                       for(g in MINI_GROUPCHATS) {
+                               if(xid == bareXID(generateXID(MINI_GROUPCHATS[g], 'groupchat'))) {
+                                       groupchat_exists = true;
+                                       
+                                       break;
+                               }
+                       }
+               }
+               
+               // Any close button to display?
+               if(((type == 'groupchat') && !groupchat_exists) || (type != 'groupchat'))
+                       html += '<a class="jm_one-action jm_close jm_images" title="' + _e("Close") + '" href="#"></a>';
+               
+               html += '</div>' + 
+                       
+                       '<div class="jm_received-messages" id="received-' + hash + '"></div>' + 
+                               '<form action="#" method="post">' + 
+                                       '<input type="text" class="jm_send-messages" name="body" autocomplete="off" />' + 
+                                       '<input type="hidden" name="xid" value="' + xid + '" />' + 
+                                       '<input type="hidden" name="type" value="' + type + '" />' + 
+                               '</form>' + 
+                       '</div>' + 
+                       
+                       '<a class="jm_pane jm_chat-tab jm_images" href="#">' + 
+                               '<span class="jm_name">' + nick.htmlEnc() + '</span>' + 
+                       '</a>' + 
+               '</div>';
+               
+               jQuery('#jappix_mini div.jm_conversations').prepend(html);
+               
+               // Get the presence of this friend
+               if(type != 'groupchat') {
+                       var selector = jQuery('#jappix_mini a#friend-' + hash + ' span.jm_presence');
+                       
+                       // Default presence
+                       var show = 'available';
+                       
+                       // Read the presence
+                       if(selector.hasClass('jm_unavailable'))
+                               show = 'unavailable';
+                       else if(selector.hasClass('jm_chat'))
+                               show = 'chat';
+                       else if(selector.hasClass('jm_away'))
+                               show = 'away';
+                       else if(selector.hasClass('jm_xa'))
+                               show = 'xa';
+                       else if(selector.hasClass('jm_dnd'))
+                               show = 'dnd';
+                       
+                       // Create the presence marker
+                       jQuery(current + ' a.jm_chat-tab').prepend('<span class="jm_presence jm_images jm_' + show + '"></span>');
+               }
+               
+               // The click events
+               chatEventsMini(type, xid, hash);
+               
+               // Join the groupchat
+               if(type == 'groupchat') {
+                       // Add the nickname value
+                       jQuery(current).attr('data-nick', escape(nickname));
+                       
+                       // Send the first groupchat presence
+                       presenceMini('', '', '', '', xid + '/' + nickname, pwd, true, handleMUCMini);
+               }
+       }
+       
+       // Focus on our pane
+       if(show_pane != false)
+               jQuery(document).oneTime(10, function() {
+                       switchPaneMini('chat-' + hash, hash);
+               });
+       
+       return false;
+}
+
+// Events on the chat tool
+function chatEventsMini(type, xid, hash) {
+       var current = '#jappix_mini #chat-' + hash;
+       
+       // Submit the form
+       jQuery(current + ' form').submit(function() {
+               return sendMessageMini(this);
+       });
+       
+       // Click on the tab
+       jQuery(current + ' a.jm_chat-tab').click(function() {
+               // Using a try/catch override IE issues
+               try {
+                       // Not yet opened: open it!
+                       if(!jQuery(this).hasClass('jm_clicked')) {
+                               // Show it!
+                               switchPaneMini('chat-' + hash, hash);
+                               
+                               // Clear the eventual notifications
+                               clearNotificationsMini(hash);
+                       }
+                       
+                       // Yet opened: close it!
+                       else
+                               switchPaneMini();
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+       
+       // Click on the close button
+       jQuery(current + ' a.jm_close').click(function() {
+               // Using a try/catch override IE issues
+               try {
+                       jQuery(current).remove();
+                       
+                       // Quit the groupchat?
+                       if(type == 'groupchat') {
+                               // Send an unavailable presence
+                               presenceMini('unavailable', '', '', '', xid + '/' + unescape(jQuery(current).attr('data-nick')));
+                               
+                               // Remove this groupchat!
+                               removeGroupchatMini(xid);
+                       }
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+       
+       // Click on the chat content
+       jQuery(current + ' div.jm_received-messages').click(function() {
+               try {
+                       jQuery(document).oneTime(10, function() {
+                               jQuery(current + ' input.jm_send-messages').focus();
+                       });
+               }
+               
+               catch(e) {}
+       });
+       
+       // Focus on the chat input
+       jQuery(current + ' input.jm_send-messages').focus(function() {
+               clearNotificationsMini(hash);
+       })
+       
+       // Change on the chat input
+       .keyup(function() {
+               jQuery(this).attr('data-value', jQuery(this).val());
+       });
+}
+
+// Shows the roster
+function showRosterMini() {
+       switchPaneMini('roster');
+       jQuery('#jappix_mini div.jm_roster').show();
+       jQuery('#jappix_mini a.jm_button').addClass('jm_clicked');
+}
+
+// Hides the roster
+function hideRosterMini() {
+       jQuery('#jappix_mini div.jm_roster').hide();
+       jQuery('#jappix_mini a.jm_button').removeClass('jm_clicked');
+}
+
+// Removes a groupchat from DOM
+function removeGroupchatMini(xid) {
+       // Remove the groupchat private chats & the groupchat buddies from the roster
+       jQuery('#jappix_mini div.jm_conversation[data-origin=' + escape(cutResource(xid)) + '], #jappix_mini div.jm_roster div.jm_grouped[data-xid=' + escape(xid) + ']').remove();
+       
+       // Update the presence counter
+       updateRosterMini();
+}
+
+// Initializes Jappix Mini
+function initializeMini() {
+       // Update the marker
+       MINI_INITIALIZED = true;
+       
+       // Send the initial presence
+       if(!MINI_ANONYMOUS)
+               presenceMini();
+       
+       // Join the groupchats
+       for(var i = 0; i < MINI_GROUPCHATS.length; i++) {
+               // Empty value?
+               if(!MINI_GROUPCHATS[i])
+                       continue;
+               
+               // Using a try/catch override IE issues
+               try {
+                       // Current chat room
+                       var chat_room = bareXID(generateXID(MINI_GROUPCHATS[i], 'groupchat'));
+                       
+                       // Open the current chat
+                       chatMini('groupchat', chat_room, getXIDNick(chat_room), hex_md5(chat_room), MINI_PASSWORDS[i], MINI_SHOWPANE);
+               }
+               
+               catch(e) {}
+       }
+       
+       // Must show the roster?
+       if(!MINI_AUTOCONNECT && !MINI_GROUPCHATS.length)
+               jQuery(document).oneTime(10, function() {
+                       showRosterMini();
+               });
+}
+
+// Displays a roster buddy
+function addBuddyMini(xid, hash, nick, groupchat) {
+       // Element
+       var element = '#jappix_mini a.jm_friend#friend-' + hash;
+       
+       // Yet added?
+       if(exists(element))
+               return false;
+       
+       // Generate the path
+       var path = '#jappix_mini div.jm_roster div.jm_buddies';
+       
+       // Groupchat buddy
+       if(groupchat) {
+               // Generate the groupchat group path
+               path = '#jappix_mini div.jm_roster div.jm_grouped[data-xid=' + escape(groupchat) + ']';
+               
+               // Must add a groupchat group?
+               if(!exists(path)) {
+                       jQuery('#jappix_mini div.jm_roster div.jm_buddies').append(
+                               '<div class="jm_grouped" data-xid="' + escape(groupchat) + '">' + 
+                                       '<div class="jm_name">' + getXIDNick(groupchat).htmlEnc() + '</div>' + 
+                               '</div>'
+                       );
+               }
+       }
+       
+       // Append this buddy content
+       var code = '<a class="jm_friend jm_offline" id="friend-' + hash + '" data-xid="' + escape(xid) + '" data-nick="' + escape(nick) +  '" data-hash="' + hash + '" href="#"><span class="jm_presence jm_images jm_unavailable"></span>' + nick.htmlEnc() + '</a>';
+       
+       if(groupchat)
+               jQuery(path).append(code);
+       else
+               jQuery(path).prepend(code);
+       
+       // Click event on this buddy
+       jQuery(element).click(function() {
+               // Using a try/catch override IE issues
+               try {
+                       chatMini('chat', xid, nick, hash);
+               }
+               
+               catch(e) {}
+               
+               finally {
+                       return false;
+               }
+       });
+       
+       return true;
+}
+
+// Removes a roster buddy
+function removeBuddyMini(hash, groupchat) {
+       // Remove the buddy from the roster
+       jQuery('#jappix_mini a.jm_friend#friend-' + hash).remove();
+       
+       // Empty group?
+       var group = '#jappix_mini div.jm_roster div.jm_grouped[data-xid=' + escape(groupchat) + ']';
+       
+       if(groupchat && !jQuery(group + ' a.jm_friend').size())
+               jQuery(group).remove();
+       
+       return true;
+}
+
+// Gets the user's roster
+function getRosterMini() {
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setQuery(NS_ROSTER);
+       con.send(iq, handleRosterMini);
+       
+       logThis('Getting roster...', 3);
+}
+
+// Handles the user's roster
+function handleRosterMini(iq) {
+       // Parse the roster
+       jQuery(iq.getQuery()).find('item').each(function() {
+               // Get the values
+               var current = jQuery(this);
+               var xid = current.attr('jid');
+               var subscription = current.attr('subscription');
+               
+               // Not a gateway
+               if(!isGateway(xid)) {
+                       var nick = current.attr('name');
+                       var hash = hex_md5(xid);
+                       
+                       // No name is defined?
+                       if(!nick)
+                               nick = getXIDNick(xid);
+                       
+                       // Action on the current buddy
+                       if(subscription == 'remove')
+                               removeBuddyMini(hash);
+                       else
+                               addBuddyMini(xid, hash, nick);
+               }
+       });
+       
+       // Not yet initialized
+       if(!MINI_INITIALIZED)
+               initializeMini();
+       
+       logThis('Roster got.', 3);
+}
+
+// Adapts the roster height to the window
+function adaptRosterMini() {
+       // Process the new height
+       var height = jQuery(window).height() - 70;
+       
+       // Apply the new height
+       jQuery('#jappix_mini div.jm_roster div.jm_buddies').css('max-height', height);
+}
+
+// Plugin launcher
+function launchMini(autoconnect, show_pane, domain, user, password) {
+       // Save infos to reconnect
+       MINI_DOMAIN = domain;
+       MINI_USER = user;
+       MINI_PASSWORD = password;
+       
+       // Anonymous mode?
+       if(!user || !password)
+               MINI_ANONYMOUS = true;
+       else
+               MINI_ANONYMOUS = false;
+       
+       // Autoconnect (only if storage available to avoid floods)?
+       if(autoconnect && hasDB())
+               MINI_AUTOCONNECT = true;
+       else
+               MINI_AUTOCONNECT = false;
+       
+       // Show pane?
+       if(show_pane)
+               MINI_SHOWPANE = true;
+       else
+               MINI_SHOWPANE = false;
+       
+       // Remove Jappix Mini
+       jQuery('#jappix_mini').remove();
+       
+       // Reconnect?
+       if(MINI_RECONNECT) {
+               logThis('Trying to reconnect (try: ' + MINI_RECONNECT + ')!');
+               
+               return createMini(domain, user, password);
+       }
+       
+       // Append the Mini stylesheet
+       jQuery('head').append('<link rel="stylesheet" href="' + JAPPIX_STATIC + 'php/get.php?t=css&amp;g=mini.xml" type="text/css" media="all" />');
+       
+       // Legacy IE stylesheet
+       if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 7))
+               jQuery('head').append('<link rel="stylesheet" href="' + JAPPIX_STATIC + 'php/get.php?t=css&amp;f=mini-ie.css" type="text/css" media="all" />');
+       
+       // Disables the browser HTTP-requests stopper
+       jQuery(document).keydown(function(e) {
+               if((e.keyCode == 27) && !isDeveloper())
+                       return false;
+       });
+       
+       // Save the page title
+       MINI_TITLE = document.title;
+       
+       // Sets the good roster max-height
+       jQuery(window).resize(adaptRosterMini);
+       
+       // Logouts when Jappix is closed
+       if(BrowserDetect.browser == 'Opera') {
+               // Emulates onbeforeunload on Opera (link clicked)
+               jQuery('a[href]:not([onclick])').click(function() {
+                       // Link attributes
+                       var href = jQuery(this).attr('href') || '';
+                       var target = jQuery(this).attr('target') || '';
+                       
+                       // Not new window or JS link
+                       if(href && !href.match(/^#/i) && !target.match(/_blank|_new/i))
+                               saveSessionMini();
+               });
+               
+               // Emulates onbeforeunload on Opera (form submitted)
+               jQuery('form:not([onsubmit])').submit(saveSessionMini);
+       }
+       
+       jQuery(window).bind('beforeunload', saveSessionMini);
+       
+       // Create the Jappix Mini DOM content
+       createMini(domain, user, password);
+       
+       logThis('Welcome to Jappix Mini! Happy coding in developer mode!');
+}
diff --git a/jappixmini/jappix/js/mobile.js b/jappixmini/jappix/js/mobile.js
new file mode 100644 (file)
index 0000000..40130a5
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+
+Jappix - An open social platform
+These are the Jappix Mobile lightweight JS script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 10/07/11
+
+*/
+
+/* BEGIN CONNECTION FUNCTIONS */
+
+function doLogin(aForm) {
+       try {
+               // Reset the panels
+               resetPanel();
+               
+               // Get the values
+               var xid = aForm.xid.value;
+               var username, domain;
+               
+               // A domain is specified
+               if(xid.indexOf('@') != -1) {
+                       username = getXIDNick(xid);
+                       domain = getXIDHost(xid);
+                       
+                       // Domain is locked and not the same
+                       if((LOCK_HOST == 'on') && (domain != HOST_MAIN)) {
+                               showThis('error');
+                               
+                               return false;
+                       }
+               }
+               
+               // No "@" in the XID, we should add the default domain
+               else {
+                       username = xid;
+                       domain = HOST_MAIN;
+               }
+               
+               var pwd = aForm.pwd.value;
+               var reg = false;
+               
+               if(aForm.reg)
+                       reg = aForm.reg.checked;
+               
+               // Enough parameters
+               if(username && domain && pwd) {
+                       // Show the info notification
+                       showThis('info');
+                       
+                       // We define the http binding parameters
+                       oArgs = new Object();
+                       
+                       if(HOST_BOSH_MAIN)
+                               oArgs.httpbase = HOST_BOSH_MAIN;
+                       else
+                               oArgs.httpbase = HOST_BOSH;
+                       
+                       // We create the new http-binding connection
+                       con = new JSJaCHttpBindingConnection(oArgs);
+                       
+                       // And we handle everything that happen
+                       con.registerHandler('message', handleMessage);
+                       con.registerHandler('presence', handlePresence);
+                       con.registerHandler('iq', handleIQ);
+                       con.registerHandler('onconnect', handleConnected);
+                       con.registerHandler('onerror', handleError);
+                       con.registerHandler('ondisconnect', handleDisconnected);
+                       
+                       // We retrieve what the user typed in the login inputs
+                       oArgs = new Object();
+                       oArgs.username = username;
+                       oArgs.domain = domain;
+                       oArgs.resource = JAPPIX_RESOURCE + ' Mobile (' + (new Date()).getTime() + ')';
+                       oArgs.pass = pwd;
+                       oArgs.secure = true;
+                       oArgs.xmllang = XML_LANG;
+                       
+                       // Register?
+                       if(reg)
+                               oArgs.register = true;
+                       
+                       // We connect !
+                       con.connect(oArgs);
+               }
+               
+               // Not enough parameters
+               else
+                       showThis('error');
+       }
+       
+       catch(e) {
+               // An error happened
+               resetPanel('error');
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+function doLogout() {
+       con.disconnect();
+}
+
+/* END CONNECTION FUNCTIONS */
+
+/* BEGIN SHOW/HIDE FUNCTIONS */
+
+function showThis(id) {
+       document.getElementById(id).style.display = 'block';
+}
+
+function hideThis(id) {
+       document.getElementById(id).style.display = 'none';
+}
+
+function resetPanel(id) {
+       // Hide the opened panels
+       hideThis('info');
+       hideThis('error');
+       
+       //Show the target panel
+       if(id)
+               showThis(id);
+}
+
+function resetDOM() {
+       // Reset the "secret" input values
+       document.getElementById('pwd').value = '';
+       
+       // Remove the useless DOM elements
+       var body = document.getElementsByTagName('body')[0];
+       body.removeChild(document.getElementById('talk'));
+       body.removeChild(document.getElementById('chat'));
+}
+
+/* END SHOW/HIDE FUNCTIONS */
+
+/* BEGIN SYSTEM FUNCTIONS */
+
+function exists(id) {
+       if(!document.getElementById(id))
+               return false;
+       else
+               return true;
+}
+
+function _e(string) {
+       return string;
+}
+
+function encodeOnclick(str) {
+       return str.replace(/'/g, '\\$&').replace(/"/g, '&quot;');
+}
+
+function getJappixLocation() {
+       var url = window.location.href;
+       
+       // If the URL has variables, remove them
+       if(url.indexOf('?') != -1)
+               url = url.split('?')[0];
+       if(url.indexOf('#') != -1)
+               url = url.split('#')[0];
+       
+       // No "/" at the end
+       if(!url.match(/(.+)\/$/))
+               url += '/';
+       
+       return url;
+}
+
+/* END SYSTEM FUNCTIONS */
+
+/* BEGIN HANDLING FUNCTIONS */
+
+function handleMessage(msg) {
+       var type = msg.getType();
+       
+       if(type == 'chat' || type == 'normal') {
+               // Get the body
+               var body = msg.getBody();
+               
+               if(body) {
+                       // Get the values
+                       var xid = cutResource(msg.getFrom());
+                       var hash = hex_md5(xid);
+                       var nick = getNick(xid, hash);
+                       
+                       // No nickname?
+                       if(!nick)
+                               nick = xid;
+               
+                       // Create the chat if it does not exist
+                       chat(xid, nick);
+               
+                       // Display the message
+                       displayMessage(xid, body, nick, hash);
+               }
+       }
+}
+
+function handlePresence(pre) {
+       // Define the variables
+       var xid = cutResource(pre.getFrom());
+       var hash = hex_md5(xid);
+       var type = pre.getType();
+       var show = pre.getShow();
+       
+       // Online buddy: show it!
+       if(!type) {
+               showThis('buddy-' + hash);
+               
+               // Display the correct presence
+               switch(show) {
+                       case 'chat':
+                               displayPresence(hash, show);
+                               break;
+                       
+                       case 'away':
+                               displayPresence(hash, show);
+                               break;
+                       
+                       case 'xa':
+                               displayPresence(hash, show);
+                               break;
+                       
+                       case 'dnd':
+                               displayPresence(hash, show);
+                               break;
+                       
+                       default:
+                               displayPresence(hash, 'available');
+                               break;
+               }
+       }
+       
+       else
+               hideThis('buddy-' + hash);
+}
+
+function handleIQ(iq) {
+       // Get the content
+       var iqFrom = iq.getFrom();
+       var iqID = iq.getID();
+       var iqQueryXMLNS = iq.getQueryXMLNS();
+       var iqType = iq.getType();
+       
+       // Create the response
+       if((iqType == 'get') && ((iqQueryXMLNS == NS_DISCO_INFO) || (iqQueryXMLNS == NS_VERSION))) {
+               var iqResponse = new JSJaCIQ();
+               iqResponse.setID(iqID);
+               iqResponse.setTo(iqFrom);
+               iqResponse.setType('result');
+       }
+       
+       // Disco#infos query
+       if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0030.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
+               
+               // We set the name of the client
+               iqQuery.appendChild(iq.appendNode('identity', {
+                       'category': 'client',
+                       'type': 'mobile',
+                       'name': 'Jappix Mobile'
+               }));
+               
+               // We set all the supported features
+               var fArray = new Array(
+                       NS_DISCO_INFO,
+                       NS_VERSION
+               );
+               
+               for(i in fArray)
+                       iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i]}));
+               
+               con.send(iqResponse);
+       }
+       
+       // Software version query
+       else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
+               /* REF: http://xmpp.org/extensions/xep-0092.html */
+               
+               var iqQuery = iqResponse.setQuery(NS_VERSION);
+               
+               iqQuery.appendChild(iq.buildNode('name', 'Jappix Mobile'));
+               iqQuery.appendChild(iq.buildNode('version', JAPPIX_VERSION));
+               iqQuery.appendChild(iq.buildNode('os', BrowserDetect.OS));
+               
+               con.send(iqResponse);
+       }
+}
+
+function handleConnected() {
+       // Reset the elements
+       hideThis('home');
+       resetPanel();
+       
+       // Create the talk page
+       document.getElementsByTagName('body')[0].innerHTML +=
+       '<div id="talk">' + 
+               '<div class="header">' + 
+                       '<div class="mobile-images"></div>' + 
+                       '<button onclick="doLogout();">' + _e("Disconnect") + '</button>' + 
+               '</div>' + 
+               
+               '<div id="roster"></div>' + 
+       '</div>' + 
+       
+       '<div id="chat">' + 
+               '<div class="header">' + 
+                       '<div class="mobile-images"></div>' + 
+                       '<button onclick="returnToRoster();">' + _e("Previous") + '</button>' + 
+               '</div>' + 
+               
+               '<div id="chans"></div>' + 
+       '</div>';
+       
+       // Get the roster items
+       getRoster();
+}
+
+function handleError(error) {
+       resetPanel('error');
+}
+
+function handleDisconnected() {
+       // Reset the elements
+       resetDOM();
+       
+       // Show the home page
+       showThis('home');
+}
+
+function handleRoster(iq) {
+       // Error: send presence anyway
+       if(!iq || (iq.getType() != 'result'))
+               return sendPresence('', 'available', 1);
+       
+       // Define some pre-vars
+       var current, xid, nick, oneBuddy, oneID, hash;
+       var roster = document.getElementById('roster');
+       
+       // Get roster items
+       var iqNode = iq.getNode();
+       var bItems = iqNode.getElementsByTagName('item');
+       
+       // Display each elements from the roster
+       for(var i = 0; i < bItems.length; i++) {
+               // Get the values
+               current = iqNode.getElementsByTagName('item').item(i);
+               xid = current.getAttribute('jid').htmlEnc();
+               nick = current.getAttribute('name');
+               hash = hex_md5(xid);
+               
+               // No defined nick?
+               if(!nick)
+                       nick = getDirectNick(xid);
+               
+               // Display the values
+               oneBuddy = document.createElement('a');
+               oneID = 'buddy-' + hash;
+               oneBuddy.setAttribute('href', '#');
+               oneBuddy.setAttribute('id', oneID);
+               oneBuddy.setAttribute('class', 'one-buddy');
+               oneBuddy.setAttribute('onclick', 'return chat(\'' + encodeOnclick(xid) + '\', \'' + encodeOnclick(nick) + '\');');
+               oneBuddy.innerHTML = nick.htmlEnc();
+               roster.appendChild(oneBuddy);
+       }
+       
+       // Start handling buddies presence
+       sendPresence('', 'available', 1);
+}
+
+/* END HANDLING FUNCTIONS */
+
+/* BEGIN SENDING FUNCTIONS */
+
+function sendMessage(aForm) {
+       try {
+               var body = aForm.body.value;
+               var xid = aForm.xid.value;
+               var hash = hex_md5(xid);
+               
+               if(body && xid) {
+                       // Send the message
+                       var aMsg = new JSJaCMessage();
+                       aMsg.setTo(xid);
+                       aMsg.setType('chat');
+                       aMsg.setBody(body);
+                       con.send(aMsg);
+                       
+                       // Clear our input
+                       aForm.body.value = '';
+                       
+                       // Display the message we sent
+                       displayMessage(xid, body, 'me', hash);
+               }
+       }
+       
+       finally {
+               return false;
+       }
+}
+
+function sendPresence(type, show, priority, status) {
+       var presence = new JSJaCPresence();
+       
+       if(type)
+               presence.setType(type);
+       if(show)
+               presence.setShow(show);
+       if(priority)
+               presence.setPriority(priority);
+       if(status)
+               presence.setStatus(status);
+       
+       con.send(presence);
+}
+
+/* END SENDING FUNCTIONS */
+
+/* BEGIN GETTING FUNCTIONS */
+
+function getRoster() {
+       iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setQuery(NS_ROSTER);
+       
+       con.send(iq, handleRoster);
+}
+
+function getDirectNick(xid) {
+       return explodeThis('@', xid, 0);
+}
+
+function getNick(xid, hash) {
+       var path = 'buddy-' + hash;
+       
+       if(exists(path))
+               return document.getElementById(path).innerHTML;
+       
+       else
+               getDirectNick(xid);
+}
+
+/* END GETTING FUNCTIONS */
+
+/* BEGIN RESOURCES FUNCTIONS */
+function explodeThis(toEx, toStr, i) {
+       // Get the index of our char to explode
+       var index = toStr.indexOf(toEx);
+       
+       // We split if necessary the string
+       if(index != -1) {
+               if(i == 0)
+                       toStr = toStr.substr(0, index);
+               else
+                       toStr = toStr.substr(index + 1);
+       }
+       
+       // We return the value
+       return toStr;
+}
+
+function cutResource(aXID) {
+       return explodeThis('/', aXID, 0);
+}
+
+function getXIDNick(aXID) {
+       return explodeThis('@', aXID, 0);
+}
+
+function getXIDHost(aXID) {
+       return explodeThis('@', aXID, 1);
+}
+/* END RESOURCES FUNCTIONS */
+
+/* BEGIN CHAT FUNCTIONS */
+
+function filter(msg) {
+       var msg = msg
+       
+       // Encode in HTML
+       .htmlEnc()
+       
+       // Highlighted text
+       .replace(/(\s|^)\*(.+)\*(\s|$)/gi,'$1<em>$2</em>$3');
+       
+       // Links
+       msg = applyLinks(msg, 'mini');
+       
+       return msg;
+}
+
+function displayMessage(xid, body, nick, hash) {
+       // Get the path
+       var path = 'content-' + hash;
+       
+       // Display the message
+       html = '<span><b';
+       
+       if(nick == 'me')
+               html += ' class="me">' + _e("You");
+       else
+               html += ' class="him">' + nick;
+       
+       html += '</b> ' + filter(body) + '</span>';
+       
+       document.getElementById(path).innerHTML += html;
+       
+       // Scroll to the last element
+       document.getElementById(path).lastChild.scrollIntoView();
+}
+
+function returnToRoster() {
+       // Hide the chats
+       hideThis('chat');
+       
+       // Show the roster
+       showThis('talk');
+}
+
+function chatSwitch(hash) {
+       // Hide the roster page
+       hideThis('talk');
+       
+       // Hide the other chats
+       var divs = document.getElementsByTagName('div');
+       
+       for(var i = 0; i < divs.length; i++) {
+               if(divs.item(i).getAttribute('class') == 'one-chat')
+                       divs.item(i).style.display = 'none';
+       }
+       
+       // Show the chat
+       showThis('chat');
+       showThis(hash);
+}
+
+function createChat(xid, nick, hash) {
+       // Define the variables
+       var chat = document.getElementById('chans');
+       var oneChat = document.createElement('div');
+       
+       // Apply the DOM modification
+       oneChat.setAttribute('id', 'chat-' + hash);
+       oneChat.setAttribute('class', 'one-chat');
+       oneChat.innerHTML = '<p>' + nick + '</p><div id="content-' + hash + '"></div><form action="#" method="post" onsubmit="return sendMessage(this);"><input type="text" name="body" /><input type="hidden" name="xid" value="' + xid + '" /><input type="submit" class="submit" value="OK" /></form>';
+       chat.appendChild(oneChat);
+}
+
+function chat(xid, nick) {
+       var hash = hex_md5(xid);
+       
+       // If the chat was not yet opened
+       if(!exists('chat-' + hash)) {
+               // No nick?
+               if(!nick)
+                       nick = getNick(xid, hash);
+               
+               // Create the chat
+               createChat(xid, nick, hash);
+       }
+       
+       // Switch to the chat
+       chatSwitch('chat-' + hash);
+       
+       return false;
+}
+
+/* END CHAT FUNCTIONS */
+
+/* BEGIN PRESENCE FUNCTIONS */
+
+function displayPresence(hash, show) {
+       document.getElementById('buddy-' + hash).setAttribute('class', 'one-buddy ' + show);
+}
+
+/* END PRESENCE FUNCTIONS */
+
+/* BEGIN DOCUMENT EVENTS FUNCTIONS */
+
+onbeforeunload = doLogout;
+
+/* END DOCUMENT EVENTS FUNCTIONS */
diff --git a/jappixmini/jappix/js/mucadmin.js b/jappixmini/jappix/js/mucadmin.js
new file mode 100644 (file)
index 0000000..3bee965
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+
+Jappix - An open social platform
+These are the mucadmin JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Maranda
+Last revision: 03/03/11
+
+*/
+
+// Opens the MUC admin popup
+function openMucAdmin(xid, aff) {
+       // Popup HTML content
+       var html_full = 
+       '<div class="top">' + _e("MUC administration") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="head mucadmin-head">' + 
+                       '<div class="head-text mucadmin-head-text">' + _e("You administrate this room") + '</div>' + 
+                       
+                       '<div class="mucadmin-head-jid">' + xid + '</div>' + 
+               '</div>' + 
+               
+               '<div class="mucadmin-forms">' + 
+                       '<div class="mucadmin-topic">' + 
+                               '<fieldset>' + 
+                                       '<legend>' + _e("Subject") + '</legend>' + 
+                                       
+                                       '<label for="topic-text">' + _e("Enter new subject") + '</label>' + 
+                                       '<textarea id="topic-text" name="room-topic" rows="8" cols="60" ></textarea>' + 
+                               '</fieldset>' + 
+                       '</div>' + 
+                       
+                       '<div class="mucadmin-conf">' + 
+                               '<fieldset>' + 
+                                       '<legend>' + _e("Configuration") + '</legend>' + 
+                                       
+                                       '<div class="results mucadmin-results"></div>' + 
+                               '</fieldset>' + 
+                       '</div>' + 
+                       
+                       '<div class="mucadmin-aut">' + 
+                               '<fieldset>' + 
+                                       '<legend>' + _e("Authorizations") + '</legend>' + 
+                                       
+                                       '<label>' + _e("Member list") + '</label>' + 
+                                       '<div class="aut-member aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'member\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                                       
+                                       '<label>' + _e("Owner list") + '</label>' + 
+                                       '<div class="aut-owner aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'owner\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                                       
+                                       '<label>' + _e("Administrator list") + '</label>' + 
+                                       '<div class="aut-admin aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'admin\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                                       
+                                       '<label>' + _e("Outcast list") + '</label>' + 
+                                       '<div class="aut-outcast aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'outcast\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                               '</fieldset>' + 
+                       '</div>' + 
+                       
+                       '<div class="mucadmin-others">' + 
+                               '<fieldset>' + 
+                                       '<legend>' + _e("Others") + '</legend>' + 
+                                       
+                                       '<label>' + _e("Destroy this MUC") + '</label>' + 
+                                       '<a href="#" onclick="return destroyMucAdmin();">' + _e("Yes, let's do it!") + '</a>' + 
+                               '</fieldset>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish save">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';
+       
+       var html_partial = 
+       '<div class="top">' + _e("MUC administration") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="head mucadmin-head">' + 
+                       '<div class="head-text mucadmin-head-text">' + _e("You administrate this room") + '</div>' + 
+                       
+                       '<div class="mucadmin-head-jid">' + xid + '</div>' + 
+               '</div>' + 
+               
+               '<div class="mucadmin-forms">' + 
+                       '<div class="mucadmin-aut">' + 
+                               '<fieldset>' + 
+                                       '<legend>' + _e("Authorizations") + '</legend>' + 
+                                       
+                                       '<label>' + _e("Member list") + '</label>' + 
+                                       '<div class="aut-member aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'member\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                                       
+                                       '<label>' + _e("Outcast list") + '</label>' + 
+                                       '<div class="aut-outcast aut-group">' + 
+                                               '<a href="#" class="aut-add" onclick="return addInputMucAdmin(\'\', \'outcast\');">' + _e("Add an input") + '</a>' + 
+                                       '</div>' + 
+                               '</fieldset>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish save">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';       
+       
+       // Create the popup
+       if(aff == 'owner')
+               createPopup('mucadmin', html_full);
+       if(aff == 'admin')
+               createPopup('mucadmin', html_partial);
+       
+       // Associate the events
+       launchMucAdmin();
+               
+       // We get the affiliated user's privileges
+       if(aff == 'owner') {
+               queryMucAdmin(xid, 'member');
+               queryMucAdmin(xid, 'owner');
+               queryMucAdmin(xid, 'admin');
+               queryMucAdmin(xid, 'outcast');
+               // We query the room to edit
+               dataForm(xid, 'muc', '', '', 'mucadmin');
+       } else if(aff == 'admin') {
+               queryMucAdmin(xid, 'member');
+               queryMucAdmin(xid, 'outcast');
+       }
+}
+
+// Closes the MUC admin popup
+function closeMucAdmin() {
+       // Destroy the popup
+       destroyPopup('mucadmin');
+       
+       return false;
+}
+
+// Removes a MUC admin input
+function removeInputMucAdmin(element) {
+       var path = $(element).parent();
+       
+       // We first hide the container of the input
+       path.hide();
+       
+       // Then, we add a special class to the input
+       path.find('input').addClass('aut-dustbin');
+       
+       return false;
+}
+
+// Adds a MUC admin input
+function addInputMucAdmin(xid, affiliation) {
+       var hash = hex_md5(xid + affiliation);
+       
+       // Add the HTML code
+       $('#mucadmin .aut-' + affiliation + ' .aut-add').after(
+               '<div class="one-aut ' + hash + '">' + 
+                       '<input id="aut-' + affiliation + '" name="' + affiliation + '" type="text" class="mucadmin-i" value="' + xid + '" />' + 
+                       '<a href="#" class="aut-remove">[-]</a>' + 
+               '</div>'
+       );
+       
+       // Click event
+       $('#mucadmin .' + hash + ' .aut-remove').click(function() {
+               return removeInputMucAdmin(this);
+       });
+       
+       // Focus on the input we added
+       if(!xid)
+               $(document).oneTime(10, function() {
+                       $('#mucadmin .' + hash + ' input').focus();
+               });
+       
+       return false;
+}
+
+// Handles the MUC admin form
+function handleMucAdminAuth(iq) {
+       // We got the authorizations results
+       $(iq.getQuery()).find('item').each(function() {
+               // We parse the received xml
+               var xid = $(this).attr('jid');
+               var affiliation = $(this).attr('affiliation');
+               
+               // We create one input for one XID
+               addInputMucAdmin(xid, affiliation);
+       });
+       
+       // Hide the wait icon
+       $('#mucadmin .wait').hide();
+       
+       logThis('MUC admin items received: ' + fullXID(getStanzaFrom(iq)));
+}
+
+// Queries the MUC admin form
+function queryMucAdmin(xid, type) {
+       // Show the wait icon
+       $('#mucadmin .wait').show();
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       
+       iq.setTo(xid);
+       iq.setType('get');
+       
+       var iqQuery = iq.setQuery(NS_MUC_ADMIN);
+       iqQuery.appendChild(iq.buildNode('item', {'affiliation': type, 'xmlns': NS_MUC_ADMIN}));
+       
+       con.send(iq, handleMucAdminAuth);
+}
+
+// Sends the new chat-room topic
+function sendMucAdminTopic(xid) {
+       // We get the new topic
+       var topic = $('.mucadmin-topic textarea').val();
+       
+       // We send the new topic if not blank
+       if(topic) {
+               var m = new JSJaCMessage();
+               m.setTo(xid);
+               m.setType('groupchat');
+               m.setSubject(topic);
+               con.send(m);
+               
+               logThis('MUC admin topic sent: ' + topic, 3);
+       }
+}
+
+// Sends the MUC admin auth form
+function sendMucAdminAuth(xid) {
+       // We define the values array
+       var types = new Array('member', 'owner', 'admin', 'outcast');
+
+       for(i in types) {
+               // We get the current type
+               var tType = types[i];
+               
+               // We loop for all the elements
+               $('.mucadmin-aut .aut-' + tType + ' input').each(function() {
+                       // We set the iq headers
+                       var iq = new JSJaCIQ();
+                       iq.setTo(xid);
+                       iq.setType('set');
+
+                       var iqQuery = iq.setQuery(NS_MUC_ADMIN);
+       
+                       // We get the needed values
+                       var value = $(this).val();
+                       
+                       // If there's a value
+                       if(value)
+                               var item = iqQuery.appendChild(iq.buildNode('item', {'jid': value, 'xmlns': NS_MUC_ADMIN}));
+                       
+                       // It the user had removed the XID
+                       if($(this).hasClass('aut-dustbin') && value)
+                               item.setAttribute('affiliation', 'none');
+                       
+                       // If the value is not blank and okay
+                       else if(value)
+                               item.setAttribute('affiliation', tType);
+       
+                       // We send the iq !
+                       con.send(iq, handleErrorReply);
+               });
+       }       
+       
+       logThis('MUC admin authorizations form sent: ' + xid, 3);
+}
+
+// Checks if the MUC room was destroyed
+function handleDestroyMucAdminIQ(iq) {
+       if(!handleErrorReply(iq)) {
+               // We close the groupchat
+               var room = fullXID(getStanzaFrom(iq));
+               var hash = hex_md5(room);
+               quitThisChat(room, hash, 'groupchat');
+               
+               // We close the muc admin popup
+               closeMucAdmin();
+               
+               // We tell the user that all is okay
+               openThisInfo(5);
+               
+               // We remove the user's favorite
+               if(existDB('favorites', room))
+                       removeThisFavorite(room, explodeThis('@', room, 0));
+               
+               logThis('MUC admin destroyed: ' + room, 3);
+       }
+       
+       // We hide the wait icon
+       $('#mucadmin .wait').hide();
+}
+
+// Destroys a MUC room
+function destroyMucAdminIQ(xid) {
+       // We ask the server to delete the room
+       var iq = new JSJaCIQ();
+       
+       iq.setTo(xid);
+       iq.setType('set');
+       var iqQuery = iq.setQuery(NS_MUC_OWNER);
+       iqQuery.appendChild(iq.buildNode('destroy', {'xmlns': NS_MUC_OWNER}));
+       
+       con.send(iq, handleDestroyMucAdminIQ);
+       
+       logThis('MUC admin destroy sent: ' + xid, 3);
+       
+       return false;
+}
+
+// Performs the MUC room destroy functions
+function destroyMucAdmin() {
+       // We get the XID of the current room
+       var xid = $('#mucadmin .mucadmin-head-jid').text();
+       
+       // We show the wait icon
+       $('#mucadmin .wait').show();
+       
+       // We send the iq
+       destroyMucAdminIQ(xid);
+}
+
+// Sends all the MUC admin stuffs
+function sendMucAdmin() {
+       // We get the XID of the current room
+       var xid = $('#mucadmin .mucadmin-head-jid').text();
+       
+       // We change the room topic
+       sendMucAdminTopic(xid);
+       
+       // We send the needed queries
+       sendDataForm('x', 'submit', 'submit', $('#mucadmin .mucadmin-results').attr('data-session'), xid, '', '', 'mucadmin');
+       sendMucAdminAuth(xid);
+}
+
+// Saves the MUC admin elements
+function saveMucAdmin() {
+       // We send the new options
+       sendMucAdmin();
+       
+       // And we quit the popup
+       return closeMucAdmin();
+}
+
+// Plugin launcher
+function launchMucAdmin() {
+       // Click events
+       $('#mucadmin .bottom .finish').click(function() {
+               if($(this).is('.cancel'))
+                       return closeMucAdmin();
+               if($(this).is('.save'))
+                       return saveMucAdmin();
+       });
+}
diff --git a/jappixmini/jappix/js/music.js b/jappixmini/jappix/js/music.js
new file mode 100644 (file)
index 0000000..f367a2b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+
+Jappix - An open social platform
+These are the music JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 25/04/11
+
+*/
+
+// Opens the music bubble
+function openMusic() {
+       var path = '.music-content';
+       
+       // Show the music bubble
+       showBubble(path);
+       
+       $(document).oneTime(10, function() {
+               $(path + ' input').focus();
+       });
+       
+       return false;
+}
+
+// Parses the music search XML
+function parseMusic(xml, type) {
+       var path = '.music-content ';
+       var content = path + '.list';
+       var path_type = content + ' .' + type;
+       
+       // Create the result container
+       if(!exists(path_type)) {
+               var code = '<div class="' + type + '"></div>';
+               
+               if(type == 'local')
+                       $(content).prepend(code);
+               else
+                       $(content).append(code);
+       }
+       
+       // Fill the results
+       $(xml).find('track').each(function() {
+               // Parse the XML
+               var id = $(this).find('id').text();
+               var title = $(this).find('name').text();
+               var artist = $(this).find('artist').text();
+               var source = $(this).find('source').text();
+               var duration = $(this).find('duration').text();
+               var uri = $(this).find('url').text();
+               var mime = $(this).find('type').text();
+               
+               // No ID?
+               if(!id)
+                       id = hex_md5(uri);
+               
+               // No MIME?
+               if(!mime)
+                       mime = 'audio/ogg';
+               
+               // Local URL?
+               if(type == 'local')
+                       uri = generateURL(uri);
+               
+               // Append the HTML code
+               $(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>');
+               
+               // Current playing song?
+               var current_song = $(path_type + ' a[data-id=' + id + ']');
+               
+               if(exists('.music-audio[data-id=' + id + ']'))
+                       current_song.addClass('playing');
+               
+               // Click event
+               current_song.click(function() {
+                       return addMusic(id,  title, artist, source, duration, uri, mime, type);
+               });
+       });
+       
+       // The search is finished
+       if(exists(content + ' .jamendo') && exists(content + ' .local')) {
+               // Get the result values
+               var jamendo = $(content + ' .jamendo').text();
+               var local = $(content + ' .local').text();
+               
+               // Enable the input
+               $(path + 'input').val('').removeAttr('disabled');
+               
+               // No result
+               if(!jamendo && !local)
+                       $(path + '.no-results').show();
+               
+               // We must put a separator between the categories
+               if(jamendo && local)
+                       $(content + ' .local').addClass('special');
+       }
+}
+
+// Sends the music search requests
+function searchMusic() {
+       var path = '.music-content ';
+       
+       // We get the input string
+       var string = $(path + 'input').val();
+       
+       // We lock the search input
+       $(path + 'input').attr('disabled', true);
+       
+       // We reset the results
+       $(path + '.list div').remove();
+       $(path + '.no-results').hide();
+       
+       // Get the Jamendo results
+       $.get('./php/music-search.php', {searchquery: string, location: 'jamendo'}, function(data) {
+               parseMusic(data, 'jamendo');
+       });
+       
+       // Get the local results
+       $.get('./php/music-search.php', {searchquery: string, location: JAPPIX_LOCATION}, function(data) {
+               parseMusic(data, 'local');
+       });
+}
+
+// Performs an action on the music player
+function actionMusic(action) {
+       try {
+               // Initialize
+               var playThis = document.getElementById('top-content').getElementsByTagName('audio')[0];
+               
+               // Nothing to play, exit
+               if(!playThis)
+                       return false;
+               
+               var stopButton = $('#top-content a.stop');
+               
+               // User play a song
+               if(action == 'play') {
+                       stopButton.show();
+                       playThis.load();
+                       playThis.play();
+                       playThis.addEventListener('ended', function() {
+                               actionMusic('stop');
+                       }, true);  
+                       
+                       logThis('Music is now playing.');
+               }
+               
+               // User stop the song or the song came to its end
+               else if(action == 'stop') {
+                       stopButton.hide();
+                       playThis.pause();
+                       $('#top-content .music').removeClass('actived');
+                       $('.music-content .list a').removeClass('playing');
+                       $('.music-audio').remove();
+                       publishMusic();
+                       
+                       logThis('Music is now stopped.');
+               }
+       }
+       
+       catch(e) {}
+       
+       finally {
+               return false;
+       }
+}
+
+// Publishes the current title over PEP
+function publishMusic(title, artist, source, duration, uri) {
+       // We share the tune on PEP if enabled
+       if(enabledPEP()) {
+               /* REF: http://xmpp.org/extensions/xep-0118.html */
+               
+               var iq = new JSJaCIQ();
+               iq.setType('set');
+               
+               // Create the main PubSub nodes
+               var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+               var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_TUNE, 'xmlns': NS_PUBSUB}));
+               var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+               var tune = item.appendChild(iq.buildNode('tune', {'xmlns': NS_TUNE}));
+               
+               // Enough data?
+               if(title || artist || source || uri) {
+                       // Data array
+                       var nodes = new Array(
+                                       'title',
+                                       'artist',
+                                       'source',
+                                       'length',
+                                       'uri'
+                                   );
+                       
+                       var values = new Array(
+                                       title,
+                                       artist,
+                                       source,
+                                       length,
+                                       uri
+                                    );
+                       
+                       // Create the children nodes
+                       for(i in nodes) {
+                               if(values[i])
+                                       tune.appendChild(iq.buildNode(nodes[i], {'xmlns': NS_TUNE}, values[i]));
+                       }
+               }
+               
+               con.send(iq);
+               
+               logThis('New tune sent: ' + title, 3);
+       }
+}
+
+// Adds a music title to the results
+function addMusic(id, title, artist, source, duration, uri, mime, type) {
+       var path = '.music-content ';
+       
+       // We remove & create a new audio tag
+       $('.music-audio').remove();
+       $(path + '.player').prepend('<audio class="music-audio" type="' + mime + '" data-id="' + id + '" />');
+       
+       // We apply the new source to the player
+       if(type == 'jamendo')
+               $('.music-audio').attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
+       else
+               $('.music-audio').attr('src', uri);
+       
+       // We play the target sound
+       actionMusic('play');
+       
+       // We set the actived class
+       $('#top-content .music').addClass('actived');
+       
+       // We set a current played track indicator
+       $(path + '.list a').removeClass('playing');
+       $(path + 'a[data-id=' + id + ']').addClass('playing');
+       
+       // We publish what we listen
+       publishMusic(title, artist, source, duration, uri);
+       
+       return false;
+}
+
+// Plugin launcher
+function launchMusic() {
+       // When music search string submitted
+       $('.music-content input').keyup(function(e) {
+               // Enter : send
+               if(e.keyCode == 13 && $(this).val())
+                       searchMusic();
+               
+               // Escape : quit
+               if(e.keyCode == 27)
+                       closeBubbles();
+       });
+}
diff --git a/jappixmini/jappix/js/name.js b/jappixmini/jappix/js/name.js
new file mode 100644 (file)
index 0000000..aad7839
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+
+Jappix - An open social platform
+These are the buddy name related JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 29/04/11
+
+*/
+
+// Gets an user name for buddy add tool
+function getAddUserName(xid) {
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       iq.setTo(xid);
+       
+       iq.appendNode('vCard', {'xmlns': NS_VCARD});
+       
+       con.send(iq, handleAddUserName);
+}
+
+// Handles an user name for buddy add tool
+function handleAddUserName(iq) {
+       // Was it an obsolete request?
+       if(!exists('.add-contact-name-get[data-for=' + escape(bareXID(getStanzaFrom(iq))) + ']'))
+               return false;
+       
+       // Reset the waiting item
+       $('.add-contact-name-get').hide().removeAttr('data-for');
+       
+       // Get the names
+       if(iq.getType() == 'result') {
+               var full_name = generateBuddyName(iq)[0];
+               
+               if(full_name)
+                       $('.add-contact-name').val(full_name);
+       }
+       
+       return false;
+}
+
+// Generates the good buddy name from a vCard IQ reply
+function generateBuddyName(iq) {
+       // Get the IQ content
+       var xml = $(iq.getNode()).find('vCard');
+       
+       // Get the full name & the nickname
+       var pFull = xml.find('FN:first').text();
+       var pNick = xml.find('NICKNAME:first').text();
+       
+       // No full name?
+       if(!pFull) {
+               // Get the given name
+               var pN = xml.find('N:first');
+               var pGiven = pN.find('GIVEN:first').text();
+               
+               if(pGiven) {
+                       pFull = pGiven;
+                       
+                       // Get the family name (optional)
+                       var pFamily = pN.find('FAMILY:first').text();
+                       
+                       if(pFamily)
+                               pFull += ' ' + pFamily;
+               }
+       }
+       
+       return [pFull, pNick];
+}
+
+// Returns the given XID buddy name
+function getBuddyName(xid) {
+       // Initialize
+       var cname, bname;
+       
+       // Cut the XID resource
+       xid = bareXID(xid);
+       
+       // This is me?
+       if(isAnonymous() && !xid)
+               bname = _e("You");
+       else if(xid == getXID())
+               bname = getName();
+       
+       // Not me!
+       else {
+               cname = $('#buddy-list .buddy[data-xid=' + escape(xid) + ']:first .buddy-name').html();
+               
+               // If the complete name exists
+               if(cname)
+                       bname = cname.revertHtmlEnc();
+               
+               // Else, we just get the nickname of the buddy
+               else
+                       bname = getXIDNick(xid);
+       }
+       
+       return bname;
+}
+
+// Gets the nickname of the user
+function getNick() {
+       // Try to read the user nickname
+       var nick = getDB('profile', 'nick');
+       
+       // No nick?
+       if(!nick)
+               nick = con.username;
+       
+       return nick;
+}
+
+// Gets the full name of the user
+function getName() {
+       // Try to read the user name
+       var name = getDB('profile', 'name');
+       
+       // No name? Use the nickname instead!
+       if(!name)
+               name = getNick();
+       
+       return name;
+}
+
+// Gets the MUC nickname of the user
+function getMUCNick(id) {
+       return unescape($('#' + id).attr('data-nick'));
+}
diff --git a/jappixmini/jappix/js/notification.js b/jappixmini/jappix/js/notification.js
new file mode 100644 (file)
index 0000000..c0f6c12
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+
+Jappix - An open social platform
+These are the notification JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+// Resets the notifications alert if no one remaining
+function closeEmptyNotifications() {
+       if(!$('.one-notification').size())
+               closeBubbles();
+}
+
+// Checks if there are pending notifications
+function checkNotifications() {
+       // Define the selectors
+       var notif = '#top-content .notifications';
+       var nothing = '.notifications-content .nothing';
+       var empty = '.notifications-content .empty';
+       
+       // Get the notifications number
+       var number = $('.one-notification').size();
+       
+       // Remove the red notify bubble
+       $(notif + ' .notify').remove();
+       
+       // Any notification?
+       if(number) {
+               $(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>');
+               $(nothing).hide();
+               $(empty).show();
+       }
+       
+       // No notification!
+       else {
+               $(empty).hide();
+               $(nothing).show();
+               
+               // Purge the social inbox node
+               purgeNotifications();
+       }
+       
+       // Update the page title
+       updateTitle();
+}
+
+// Creates a new notification
+function newNotification(type, from, data, body, id, inverse) {
+       if(!type || !from)
+               return;
+       
+       // Generate an ID hash
+       if(!id)
+               var id = hex_md5(type + from);
+       
+       // Generate the text to be displayed
+       var text, action, code;
+       var yes_path = 'href="#"';
+       
+       // User things
+       from = bareXID(from);
+       var hash = hex_md5(from);
+       
+       switch(type) {
+               case 'subscribe':
+                       // Get the name to display
+                       var display_name = data[1];
+                       
+                       if(!display_name)
+                               display_name = data[0];
+                       
+                       text = '<b>' + display_name.htmlEnc() + '</b> ' + _e("would like to add you as a friend.") + ' ' + _e("Do you accept?");
+                       
+                       break;
+               
+               case 'invite_room':
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + _e("would like you to join this chatroom:") + ' <em>' + data[0].htmlEnc() + '</em> ' + _e("Do you accept?");
+                       
+                       break;
+               
+               case 'request':
+                       text = '<b>' + from.htmlEnc() + '</b> ' + _e("would like to get authorization.") + ' ' + _e("Do you accept?");
+                       
+                       break;
+               
+               case 'send':
+                       yes_path = 'href="' + encodeQuotes(data[1]) + '" target="_blank"';
+                       
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("would like to send you a file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>') + ' ' + _e("Do you accept?");
+                       
+                       break;
+               
+               case 'send_pending':
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has received a file exchange request: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'send_accept':
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has accepted to received your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'send_reject':
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("has rejected to receive your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'send_fail':
+                       text = '<b>' + getBuddyName(from).htmlEnc() + '</b> ' + printf(_e("could not receive your file: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'rosterx':
+                       text = printf(_e("Do you want to see the friends %s suggests you?").htmlEnc(), '<b>' + getBuddyName(from).htmlEnc() + '</b>');
+                       
+                       break;
+               
+               case 'comment':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("commented an item you follow: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'like':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("liked your post: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'quote':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("quoted you somewhere: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'wall':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("published on your wall: “%s”.").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'photo':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("tagged you in a photo (%s).").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               case 'video':
+                       text = '<b>' + data[0].htmlEnc() + '</b> ' + printf(_e("tagged you in a video (%s).").htmlEnc(), '<em>' + truncate(body, 25).htmlEnc() + '</em>');
+                       
+                       break;
+               
+               default:
+                       break;
+       }
+       
+       // No text?
+       if(!text)
+               return;
+       
+       // Action links?
+       if((type == 'send_pending') || (type == 'send_accept') || (type == 'send_reject') || (type == 'send_fail') || (type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
+               action = '<a href="#" class="no">' + _e("Hide") + '</a>';
+               
+               // Any parent link?
+               if((type == 'comment') && data[2])
+                       action = '<a href="#" class="yes">' + _e("Show") + '</a>' + action;
+       }
+       
+       else    
+               action = '<a ' + yes_path + ' class="yes">' + _e("Yes") + '</a><a href="#" class="no">' + _e("No") + '</a>';
+       
+       if(text) {
+               // We display the notification
+               if(!exists('.notifications-content .' + id)) {
+                       // We create the html markup depending of the notification type
+                       code = '<div class="one-notification ' + id + ' ' + hash + '" title="' + encodeQuotes(body) + '" data-type="' + encodeQuotes(type) + '">' + 
+                                       '<div class="avatar-container">' + 
+                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                       '</div>' + 
+                                       
+                                       '<p class="notification-text">' + text + '</p>' + 
+                                       '<p class="notification-actions">' + 
+                                               '<span class="talk-images" />' + 
+                                               action + 
+                                       '</p>' + 
+                              '</div>';
+                       
+                       // Add the HTML code
+                       if(inverse)
+                               $('.notifications-content .nothing').before(code);
+                       else
+                               $('.notifications-content .empty').after(code);
+                       
+                       // Play a sound to alert the user
+                       soundPlay(2);
+                       
+                       // The yes click function
+                       $('.' + id + ' a.yes').click(function() {
+                               actionNotification(type, data, 'yes', id);
+                               
+                               if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank'))
+                                       return false;
+                       });
+                       
+                       // The no click function
+                       $('.' + id + ' a.no').click(function() {
+                               return actionNotification(type, data, 'no', id);
+                       });
+                       
+                       // Get the user avatar
+                       getAvatar(from, 'cache', 'true', 'forget');
+               }
+       }
+       
+       // We tell the user he has a new pending notification
+       checkNotifications();
+       
+       logThis('New notification: ' + from, 3);
+}
+
+// Performs an action on a given notification
+function actionNotification(type, data, value, id) {
+       // We launch a function depending of the type
+       if((type == 'subscribe') && (value == 'yes'))
+               acceptSubscribe(data[0], data[1]);
+       
+       else if((type == 'subscribe') && (value == 'no'))
+               sendSubscribe(data[0], 'unsubscribed');
+       
+       else if((type == 'invite_room') && (value == 'yes'))
+               checkChatCreate(data[0], 'groupchat');
+       
+       else if(type == 'request')
+               requestReply(value, data[0]);
+       
+       if((type == 'send') && (value == 'yes'))
+               replyOOB(data[0], data[3], 'accept', data[2], data[4]);
+       
+       else if((type == 'send') && (value == 'no'))
+               replyOOB(data[0], data[3], 'reject', data[2], data[4]);
+       
+       else if((type == 'rosterx') && (value == 'yes'))
+               openRosterX(data[0]);
+       
+       else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
+               if(value == 'yes') {
+                       // Get the microblog item
+                       fromInfosMicroblog(data[2]);
+                       
+                       // Append the marker
+                       $('#channel .top.individual').append('<input type="hidden" name="comments" value="' + encodeQuotes(data[1]) + '" />');
+               }
+               
+               removeNotification(data[3]);
+       }
+       
+       // We remove the notification
+       $('.notifications-content .' + id).remove();
+       
+       // We check if there's any other pending notification
+       closeEmptyNotifications();
+       checkNotifications();
+       
+       return false;
+}
+
+// Clear the social notifications
+function clearNotifications() {
+       // Remove notifications
+       $('.one-notification').remove();
+       
+       // Refresh
+       closeEmptyNotifications();
+       checkNotifications();
+       
+       return false;
+}
+
+// Gets the pending social notifications
+function getNotifications() {
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+       
+       con.send(iq, handleNotifications);
+       
+       logThis('Getting social notifications...');
+}
+
+// Handles the social notifications
+function handleNotifications(iq) {
+       // Any error?
+       if((iq.getType() == 'error') && $(iq.getNode()).find('item-not-found').size()) {
+               // The node may not exist, create it!
+               setupMicroblog('', NS_URN_INBOX, '1', '1000000', 'whitelist', 'open', true);
+               
+               logThis('Error while getting social notifications, trying to reconfigure the Pubsub node!', 2);
+       }
+       
+       // Selector
+       var items = $(iq.getNode()).find('item');
+       
+       // Should we inverse?
+       var inverse = true;
+       
+       if(items.size() == 1)
+               inverse = false;
+       
+       // Parse notifications
+       items.each(function() {
+               // Parse the current item
+               var current_item = $(this).attr('id');
+               var current_type = $(this).find('link[rel=via]:first').attr('title');
+               var current_href = $(this).find('link[rel=via]:first').attr('href');
+               var current_parent_href = $(this).find('link[rel=related]:first').attr('href');
+               var current_xid = explodeThis(':', $(this).find('source author uri').text(), 1);
+               var current_name = $(this).find('source author name').text();
+               var current_text = $(this).find('content[type=text]:first').text();
+               var current_bname = getBuddyName(current_xid);
+               var current_id = hex_md5(current_type + current_xid + current_href + current_text);
+               
+               // Choose the good name!
+               if(!current_name || (current_bname != getXIDNick(current_xid)))
+                       current_name = current_bname;
+               
+               // Create it!
+               newNotification(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse);
+       });
+       
+       logThis(items.size() + ' social notification(s) got!', 3);
+}
+
+// Sends a social notification
+function sendNotification(xid, type, href, text, parent) {
+       // Notification ID
+       var id = hex_md5(xid + text + getTimeStamp());
+       
+       // IQ
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       iq.setTo(xid);
+       
+       // ATOM content
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+       var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
+       
+       // Notification author (us)
+       var Source = entry.appendChild(iq.buildNode('source', {'xmlns': NS_ATOM}));
+       var author = Source.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
+       author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, getName()));
+       author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + getXID()));
+       
+       // Notification content
+       entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, getXMPPTime('utc')));
+       entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, text));
+       entry.appendChild(iq.buildNode('link', {'rel': 'via', 'title': type, 'href': href, 'xmlns': NS_ATOM}));
+       
+       // Any parent item?
+       if(parent && parent[0] && parent[1] && parent[2]) {
+               // Generate the parent XMPP URI
+               var parent_href = 'xmpp:' + parent[0] + '?;node=' + encodeURIComponent(parent[1]) + ';item=' + encodeURIComponent(parent[2]);
+               
+               entry.appendChild(iq.buildNode('link', {'rel': 'related', 'href': parent_href, 'xmlns': NS_ATOM}));
+       }
+       
+       con.send(iq);
+       
+       logThis('Sending a social notification to ' + xid + ' (type: ' + type + ')...');
+}
+
+// Removes a social notification
+function removeNotification(id) {
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var retract = pubsub.appendChild(iq.buildNode('retract', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
+       retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
+       
+       con.send(iq);
+}
+
+// Purge the social notifications
+function purgeNotifications() {
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
+       pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB_OWNER}));
+       
+       con.send(iq);
+       
+       return false;
+}
+
+// Adapt the notifications bubble max-height
+function adaptNotifications() {
+       // Process the new height
+       var max_height = $('#right-content').height() - 22;
+       
+       // New height too small
+       if(max_height < 250)
+               max_height = 250;
+       
+       // Apply the new height
+       $('.notifications-content .tools-content-subitem').css('max-height', max_height);
+}
+
+// Plugin launcher
+function launchNotifications() {
+       // Adapt the notifications height
+       adaptNotifications();
+}
+
+// Window resize event handler
+$(window).resize(adaptNotifications);
diff --git a/jappixmini/jappix/js/oob.js b/jappixmini/jappix/js/oob.js
new file mode 100644 (file)
index 0000000..7242261
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+
+Jappix - An open social platform
+These are the Out of Band Data JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+// Sends an OOB request to someone
+function sendOOB(to, type, url, desc) {
+       // IQ stanza?
+       if(type == 'iq') {
+               // Get some values
+               var id = hex_md5(genID() + to + url + desc);
+               to = getHighestResource(to);
+               
+               // IQs cannot be sent to offline users
+               if(!to)
+                       return;
+               
+               // Register the ID
+               setDB('send/url', id, url);
+               setDB('send/desc', id, desc);
+               
+               var aIQ = new JSJaCIQ();
+               aIQ.setTo(fullXID(to));
+               aIQ.setType('set');
+               aIQ.setID(id);
+               
+               // Append the query content
+               var aQuery = aIQ.setQuery(NS_IQOOB);
+               aQuery.appendChild(aIQ.buildNode('url', {'xmlns': NS_IQOOB}, url));
+               aQuery.appendChild(aIQ.buildNode('desc', {'xmlns': NS_IQOOB}, desc));
+               
+               con.send(aIQ);
+       }
+       
+       // Message stanza?
+       else {
+               var aMsg = new JSJaCMessage();
+               aMsg.setTo(bareXID(to));
+               
+               // Append the content
+               aMsg.setBody(desc);
+               var aX = aMsg.appendNode('x', {'xmlns': NS_XOOB});
+               aX.appendChild(aMsg.buildNode('url', {'xmlns': NS_XOOB}, url));
+               
+               con.send(aMsg);
+       }
+       
+       logThis('Sent OOB request to: ' + to + ' (' + desc + ')');
+}
+
+// Handles an OOB request
+function handleOOB(from, id, type, node) {
+       var xid = url = desc = '';
+       
+       // IQ stanza?
+       if(type == 'iq') {
+               xid = fullXID(from);
+               url = $(node).find('url').text();
+               desc = $(node).find('desc').text();
+       }
+       
+       // Message stanza?
+       else {
+               xid = bareXID(from);
+               url = $(node).find('url').text();
+               desc = $(node).find('body').text();
+       }
+       
+       // No desc?
+       if(!desc)
+               desc = url;
+       
+       // Open a new notification
+       if(type && xid && url && desc)
+               newNotification('send', xid, [xid, url, type, id, node], desc, hex_md5(xid + url + desc + id));
+}
+
+// Replies to an OOB request
+function replyOOB(to, id, choice, type, node) {
+       // Not IQ type?
+       if(type != 'iq')
+               return;
+       
+       // New IQ
+       var aIQ = new JSJaCIQ();
+       aIQ.setTo(to);
+       aIQ.setID(id);
+       
+       // OOB request accepted
+       if(choice == 'accept') {
+               aIQ.setType('result');
+               
+               logThis('Accepted file request from: ' + to, 3);
+       }
+       
+       // OOB request rejected
+       else {
+               aIQ.setType('error');
+               
+               // Append stanza content
+               for(var i = 0; i < node.childNodes.length; i++)
+                       aIQ.getNode().appendChild(node.childNodes.item(i).cloneNode(true));
+               
+               // Append error content
+               var aError = aIQ.appendNode('error', {'xmlns': NS_CLIENT, 'code': '406', 'type': 'modify'});
+               aError.appendChild(aIQ.buildNode('not-acceptable', {'xmlns': NS_STANZAS}));
+               
+               logThis('Rejected file request from: ' + to, 3);
+       }
+       
+       con.send(aIQ);
+}
+
+// Wait event for OOB upload
+function waitUploadOOB() {
+       // Append the wait icon
+       $('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem *').hide();
+       $('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem').append('<div class="wait wait-medium"></div>');
+       
+       // Lock the bubble
+       $('#page-engine .chat-tools-file:not(.mini)').addClass('mini');
+}
+
+// Success event for OOB upload
+function handleUploadOOB(responseXML) {
+       // Data selector
+       var dData = $(responseXML).find('jappix');
+       
+       // Get the values
+       var fID = dData.find('id').text();
+       var fURL = dData.find('url').text();
+       var fDesc = dData.find('desc').text();
+       
+       // Get the OOB values
+       var oob_has;
+       
+       // No ID provided?
+       if(!fID)
+               oob_has = ':has(.wait)';
+       else
+               oob_has = ':has(#oob-upload input[value=' + fID + '])';
+       
+       var xid = $('#page-engine .page-engine-chan' + oob_has).attr('data-xid');
+       var oob_type = $('#page-engine .chat-tools-file' + oob_has).attr('data-oob');
+       
+       // Reset the file send tool
+       $('#page-engine .chat-tools-file' + oob_has).removeClass('mini');
+       $('#page-engine .bubble-file' + oob_has).remove();
+       
+       // Not available?
+       if($('#page-engine .chat-tools-file' + oob_has).is(':hidden') && (oob_type == 'iq')) {
+               openThisError(4);
+               
+               // Remove the file we sent
+               if(fURL)
+                       $.get(fURL + '&action=remove');
+       }
+       
+       // Everything okay?
+       else if(fURL && fDesc && !dData.find('error').size()) {
+               // Send the OOB request
+               sendOOB(xid, oob_type, fURL, fDesc);
+               
+               // Notify the sender
+               newNotification('send_pending', xid, [xid, fURL, oob_type, '', ''], fDesc, hex_md5(fURL + fDesc + fID));
+               
+               logThis('File request sent.', 3);
+       }
+       
+       // Upload error?
+       else {
+               openThisError(4);
+               
+               logThis('Error while sending the file: ' + dData.find('error').text(), 1);
+       }
+}
diff --git a/jappixmini/jappix/js/options.js b/jappixmini/jappix/js/options.js
new file mode 100644 (file)
index 0000000..0463af4
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+
+Jappix - An open social platform
+These are the options JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 17/07/11
+
+*/
+
+// Opens the options popup
+function optionsOpen() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Edit options") + '</div>' + 
+       
+       '<div class="tab">' + 
+               '<a href="#" class="tab-active" data-key="1">' + _e("General") + '</a>' + 
+               '<a href="#" class="pubsub-hidable" data-key="2">' + _e("Channel") + '</a>' + 
+               '<a href="#" data-key="3">' + _e("Account") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="content">' + 
+               '<div id="conf1" class="lap-active one-lap forms">' + 
+                       '<fieldset class="privacy">' + 
+                               '<legend>' + _e("Privacy") + '</legend>' + 
+                               
+                               '<label for="geolocation" class="pep-hidable">' + _e("Geolocation") + '</label>' + 
+                               '<input id="geolocation" type="checkbox" class="pep-hidable" />' + 
+                               
+                               '<label for="archiving" class="archives-hidable pref">' + _e("Message archiving") + '</label>' + 
+                               '<input id="archiving" type="checkbox" class="archives-hidable pref" />' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Application") + '</legend>' + 
+                               
+                               '<label for="sounds">' + _e("Sounds") + '</label>' + 
+                               '<input id="sounds" type="checkbox" />' + 
+                               
+                               '<label for="showall">' + _e("Show all friends") + '</label>' + 
+                               '<input id="showall" type="checkbox" />' + 
+                               
+                               '<label for="integratemedias">' + _e("Media integration") + '</label>' + 
+                               '<input id="integratemedias" type="checkbox" />' + 
+                               
+                               '<label class="xmpplinks-hidable">' + _e("XMPP links") + '</label>' + 
+                               '<a href="#" class="linked xmpp-links xmpplinks-hidable">' + _e("Open XMPP links with Jappix") + '</a>' + 
+                       '</fieldset>' + 
+               '</div>' + 
+               
+               '<div id="conf2" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Channel") + '</legend>' + 
+                               
+                               '<label>' + _e("Empty") + '</label>' + 
+                               '<a href="#" class="linked empty-channel">' + _e("Empty channel") + '</a>' + 
+                               
+                               '<label>' + _e("Persistent") + '</label>' + 
+                               '<input id="persistent" type="checkbox" />' + 
+                               
+                               '<label>' + _e("Maximum notices") + '</label>' + 
+                               '<select id="maxnotices">' + 
+                                       '<option value="1">1</option>' + 
+                                       '<option value="100">100</option>' + 
+                                       '<option value="1000">1000</option>' + 
+                                       '<option value="10000">10000</option>' + 
+                                       '<option value="100000">100000</option>' + 
+                                       '<option value="1000000">1000000</option>' + 
+                               '</select>' + 
+                       '</fieldset>' + 
+                       
+                       '<div class="sub-ask sub-ask-empty sub-ask-element">' + 
+                               '<div class="sub-ask-top">' + 
+                                       '<div class="sub-ask-title">' + _e("Empty channel") + '</div>' + 
+                                       '<a href="#" class="sub-ask-close">X</a>' + 
+                               '</div>' + 
+                               
+                               '<div class="sub-ask-content">' + 
+                                       '<label>' + _e("Password") + '</label>' + 
+                                       '<input type="password" class="purge-microblog check-empty" required="" />' + 
+                               '</div>' + 
+                               
+                               '<a href="#" class="sub-ask-bottom">' + _e("Empty") + ' &raquo;</a>' + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div id="conf3" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Account") + '</legend>' + 
+                               
+                               '<label>' + _e("Password") + '</label>' + 
+                               '<a href="#" class="linked change-password">' + _e("Change password") + '</a>' + 
+                               
+                               '<label>' + _e("Delete") + '</label>' + 
+                               '<a href="#" class="linked delete-account">' + _e("Delete account") + '</a>' + 
+                       '</fieldset>' + 
+                               
+                       '<div class="sub-ask sub-ask-pass sub-ask-element">' + 
+                               '<div class="sub-ask-top">' + 
+                                       '<div class="sub-ask-title">' + _e("Change password") + '</div>' + 
+                                       '<a href="#" class="sub-ask-close">X</a>' + 
+                               '</div>' + 
+                               
+                               '<div class="sub-ask-content">' + 
+                                       '<label>' + _e("Old") + '</label>' + 
+                                       '<input type="password" class="password-change old" required="" />' + 
+                                       
+                                       '<label>' + _e("New (2 times)") + '</label>' + 
+                                       '<input type="password" class="password-change new1" required="" />' + 
+                                       '<input type="password" class="password-change new2" required="" />' + 
+                               '</div>' + 
+                               
+                               '<a href="#" class="sub-ask-bottom">' + _e("Continue") + ' &raquo;</a>' + 
+                       '</div>' + 
+                       
+                       '<div class="sub-ask sub-ask-delete sub-ask-element">' + 
+                               '<div class="sub-ask-top">' + 
+                                       '<div class="sub-ask-title">' + _e("Delete account") + '</div>' + 
+                                       '<a href="#" class="sub-ask-close">X</a>' + 
+                               '</div>' + 
+                               
+                               '<div class="sub-ask-content">' + 
+                                       '<label>' + _e("Password") + '</label>' + 
+                                       '<input type="password" class="delete-account check-password" required="" />' + 
+                               '</div>' + 
+                               
+                               '<a href="#" class="sub-ask-bottom">' + _e("Delete") + ' &raquo;</a>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish save">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('options', html);
+       
+       // Apply the features
+       applyFeatures('options');
+       
+       // Associate the events
+       launchOptions();
+       
+       return false;
+}
+
+// Closes the options popup
+function closeOptions() {
+       // Destroy the popup
+       destroyPopup('options');
+       
+       return false;
+}
+
+// Checks whether the options are loaded or not
+function loadedOptions() {
+       if($('.options-hidable').is(':visible'))
+               return true;
+       
+       return false;
+}
+
+// Switches between the options tabs
+function switchOptions(id) {
+       $('#options .one-lap').hide();
+       $('#options #conf' + id).show();
+       $('#options .tab a').removeClass('tab-active');
+       $('#options .tab a[data-key=' + id + ']').addClass('tab-active');
+       
+       return false;
+}
+
+// Manages the options wait item
+function waitOptions(id) {
+       var sOptions = $('#options .content');
+       
+       // Remove the current item class
+       sOptions.removeClass(id);
+       
+       // Hide the waiting items if all was received
+       if(!sOptions.hasClass('microblog') && !sOptions.hasClass('archives')) {
+               $('#options .wait').hide();
+               $('#options .finish:first').removeClass('disabled');
+       }
+}
+
+// Sends the options to the XMPP server
+function storeOptions() {
+       // Get the values
+       var sounds = getDB('options', 'sounds');
+       var geolocation = getDB('options', 'geolocation');
+       var showall = getDB('options', 'roster-showall');
+       var integratemedias = getDB('options', 'integratemedias');
+       var status = getDB('options', 'presence-status');
+       
+       // Create an array to be looped
+       var oType = new Array('sounds', 'geolocation', 'roster-showall', 'integratemedias', 'presence-status');
+       var oContent = new Array(sounds, geolocation, showall, integratemedias, status);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var query = iq.setQuery(NS_PRIVATE);
+       var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
+       
+       // Loop the array
+       for(i in oType)
+               storage.appendChild(iq.buildNode('option', {'type': oType[i], 'xmlns': NS_OPTIONS}, oContent[i]));
+       
+       con.send(iq, handleStoreOptions);
+       
+       logThis('Storing options...', 3);
+}
+
+// Handles the option storing
+function handleStoreOptions(iq) {
+       if(!iq || (iq.getType() != 'result'))
+               logThis('Options not stored.', 2);
+       else
+               logThis('Options stored.', 3);
+}
+
+// Saves the user options
+function saveOptions() {
+       // We apply the sounds
+       var sounds = '0';
+       
+       if($('#sounds').filter(':checked').size())
+               sounds = '1';
+       
+       setDB('options', 'sounds', sounds);
+       
+       // We apply the geolocation
+       if($('#geolocation').filter(':checked').size()) {
+               setDB('options', 'geolocation', '1');
+               
+               // We geolocate the user on the go
+               geolocate();
+       }
+       
+       else {
+               setDB('options', 'geolocation', '0');
+               
+               // We delete the geolocation informations
+               sendPosition();
+               removeDB('geolocation', 'now');
+       }
+       
+       // We apply the roster show all
+       if($('#showall').filter(':checked').size()) {
+               setDB('options', 'roster-showall', '1');
+               showAllBuddies('options');
+       }
+       
+       else {
+               setDB('options', 'roster-showall', '0');
+               showOnlineBuddies('options');
+       }
+       
+       // We apply the media integration
+       var integratemedias = '0';
+       
+       if($('#integratemedias').filter(':checked').size())
+               integratemedias = '1';
+       
+       setDB('options', 'integratemedias', integratemedias);
+       
+       // We apply the message archiving
+       if(enabledArchives('pref')) {
+               var aEnabled = false;
+               
+               if($('#archiving').filter(':checked').size())
+                       aEnabled = true;
+               
+               configArchives(aEnabled);
+       }
+       
+       // We apply the microblog configuration
+       var persist = '0';
+       var maximum = $('#maxnotices').val();
+       
+       if($('#persistent').filter(':checked').size())
+               persist = '1';
+       
+       if(enabledPEP() && enabledPubSub())
+               setupMicroblog('', NS_URN_MBLOG, persist, maximum, '', '', false);
+       
+       // We send the options to the database
+       storeOptions();
+       
+       // Close the options
+       closeOptions();
+       
+       return false;
+}
+
+// Handles the password changing
+function handlePwdChange(iq) {
+       // Remove the general wait item
+       removeGeneralWait();
+       
+       // If no errors
+       if(!handleErrorReply(iq)) {
+               clearLastSession();
+               quit();
+               openThisInfo(1);
+               
+               logThis('Password changed.', 3);
+       }
+       
+       else
+               logThis('Password not changed.', 2);
+}
+
+// Sends the new account password
+function sendNewPassword() {
+       /* REF: http://xmpp.org/extensions/xep-0077.html#usecases-changepw */
+       
+       var password0 = $('#options .old').val();
+       var password1 = $('#options .new1').val();
+       var password2 = $('#options .new2').val();
+       
+       if ((password1 == password2) && (password0 == getPassword())) {
+               // We show the waiting image
+               showGeneralWait();
+               
+               // We send the IQ
+               var iq = new JSJaCIQ();
+               
+               iq.setTo(getServer());
+               iq.setType('set');
+               
+               var iqQuery = iq.setQuery(NS_REGISTER);
+               
+               iqQuery.appendChild(iq.buildNode('username', {'xmlns': NS_REGISTER}, con.username));
+               iqQuery.appendChild(iq.buildNode('password', {'xmlns': NS_REGISTER}, password1));
+               
+               con.send(iq, handlePwdChange);
+               
+               logThis('Password change sent.', 3);
+       }
+       
+       else {
+               $('.sub-ask-pass input').each(function() {
+                       var select = $(this);
+                       
+                       if(!select.val())
+                               $(document).oneTime(10, function() {
+                                       select.addClass('please-complete').focus();
+                               });
+                       else
+                               select.removeClass('please-complete');  
+               });
+               
+               if(password0 != getPassword())
+                       $(document).oneTime(10, function() {
+                               $('#options .old').addClass('please-complete').focus();
+                       });
+               if(password1 != password2)
+                       $(document).oneTime(10, function() {
+                               $('#options .new1, #options .new2').addClass('please-complete').focus();
+                       });
+       }
+       
+       return false;
+}
+
+// Handles the account deletion request
+function handleAccDeletion(iq) {
+       // Remove the general wait item
+       removeGeneralWait();
+       
+       // If no errors
+       if(!handleErrorReply(iq)) {
+               clearLastSession();
+               destroyTalkPage();
+               openThisInfo(2);
+               logout();
+               
+               logThis('Account deleted.', 3);
+       }
+       
+       else
+               logThis('Account not deleted.', 2);
+}
+
+// Purge the user's microblog items
+function purgeMyMicroblog() {
+       /* REF: http://xmpp.org/extensions/xep-0060.html#owner-purge */
+       
+       var password = $('#options .check-empty').val();
+       
+       if(password == getPassword()) {
+               // Send the IQ to remove the item (and get eventual error callback)
+               var iq = new JSJaCIQ();
+               iq.setType('set');
+               
+               var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
+               pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB_OWNER}));
+               
+               con.send(iq, handleMicroblogPurge);
+               
+               // Hide the tool
+               $('#options .sub-ask').hide();
+               
+               logThis('Microblog purge sent.', 3);
+       }
+       
+       else {
+               var selector = $('#options .check-empty');
+               
+               if(password != getPassword())
+                       $(document).oneTime(10, function() {
+                               selector.addClass('please-complete').focus();
+                       });
+               else
+                       selector.removeClass('please-complete');
+       }
+       
+       return false;
+}
+
+// Handles the microblog purge
+function handleMicroblogPurge(iq) {
+       // If no errors
+       if(!handleErrorReply(iq)) {
+               // Remove the microblog items
+               $('.one-update.update_' + hex_md5(getXID())).remove();
+               
+               logThis('Microblog purged.', 3);
+       }
+       
+       else
+               logThis('Microblog not purged.', 2);
+}
+
+// Deletes the user's account
+function deleteMyAccount() {
+       /* REF: http://xmpp.org/extensions/xep-0077.html#usecases-cancel */
+       
+       var password = $('#options .check-password').val();
+       
+       if(password == getPassword()) {
+               // We show the waiting image
+               showGeneralWait();
+               
+               // We send the IQ
+               var iq = new JSJaCIQ();
+               iq.setType('set');
+               
+               var iqQuery = iq.setQuery(NS_REGISTER);
+               iqQuery.appendChild(iq.buildNode('remove', {'xmlns': NS_REGISTER}));
+               
+               con.send(iq, handleAccDeletion);
+               
+               logThis('Delete account sent.', 3);
+       }
+       
+       else {
+               var selector = $('#options .check-password');
+               
+               if(password != getPassword())
+                       $(document).oneTime(10, function() {
+                               selector.addClass('please-complete').focus();
+                       });
+               else
+                       selector.removeClass('please-complete');
+       }
+       
+       return false;
+}
+
+// Loads the user options
+function loadOptions() {
+       // Process the good stuffs, depending of the server features
+       var enabled_archives_pref = enabledArchives('pref');
+       var enabled_pubsub = enabledPubSub();
+       var enabled_pep = enabledPEP();
+       var sWait = $('#options .content');
+       
+       // Show the waiting items if necessary
+       if(enabled_archives_pref || (enabled_pep && enabled_pubsub)) {
+               $('#options .wait').show();
+               $('#options .finish:first').addClass('disabled');
+       }
+       
+       // We get the archiving configuration
+       if(enabled_archives_pref) {
+               sWait.addClass('archives');
+               getConfigArchives();
+       }
+       
+       // We get the microblog configuration
+       if(enabled_pubsub && enabled_pep) {
+               sWait.addClass('microblog');
+               getConfigMicroblog();
+       }
+       
+       // We show the "privacy" form if something is visible into it
+       if(enabled_archives_pref || enabled_pep)
+               $('#options fieldset.privacy').show();
+       
+       // We get the values of the forms for the sounds
+       if(getDB('options', 'sounds') == '0')
+               $('#sounds').attr('checked', false);
+       else
+               $('#sounds').attr('checked', true);
+       
+       // We get the values of the forms for the geolocation
+       if(getDB('options', 'geolocation') == '1')
+               $('#geolocation').attr('checked', true);
+       else
+               $('#geolocation').attr('checked', false);
+       
+       // We get the values of the forms for the roster show all
+       if(getDB('options', 'roster-showall') == '1')
+               $('#showall').attr('checked', true);
+       else
+               $('#showall').attr('checked', false);
+       
+       // We get the values of the forms for the integratemedias
+       if(getDB('options', 'integratemedias') == '0')
+               $('#integratemedias').attr('checked', false);
+       else
+               $('#integratemedias').attr('checked', true);
+}
+
+// Plugin launcher
+function launchOptions() {
+       // Click events
+       $('#options .tab a').click(function() {
+               // Yet active?
+               if($(this).hasClass('tab-active'))
+                       return false;
+               
+               // Switch to the good tab
+               var key = parseInt($(this).attr('data-key'));
+               
+               return switchOptions(key);
+       });
+       
+       $('#options .linked').click(function() {
+               $('#options .sub-ask').hide();
+       });
+       
+       $('#options .xmpp-links').click(function() {
+               xmppLinksHandler();
+               
+               return false;
+       });
+       
+       $('#options .empty-channel').click(function() {
+               var selector = '#options .sub-ask-empty';
+               
+               $(selector).show();
+               
+               $(document).oneTime(10, function() {
+                       $(selector + ' input').focus();
+               });
+               
+               return false;
+       });
+       
+       $('#options .change-password').click(function() {
+               var selector = '#options .sub-ask-pass';
+               
+               $(selector).show();
+               
+               $(document).oneTime(10, function() {
+                       $(selector + ' input:first').focus();
+               });
+               
+               return false;
+       });
+       
+       $('#options .delete-account').click(function() {
+               var selector = '#options .sub-ask-delete';
+               
+               $(selector).show();
+               
+               $(document).oneTime(10, function() {
+                       $(selector + ' input').focus();
+               });
+               
+               return false;
+       });
+       
+       $('#options .sub-ask-pass .sub-ask-bottom').click(function() {
+               return sendNewPassword();
+       });
+       
+       $('#options .sub-ask-empty .sub-ask-bottom').click(function() {
+               return purgeMyMicroblog();
+       });
+       
+       $('#options .sub-ask-delete .sub-ask-bottom').click(function() {
+               return deleteMyAccount();
+       });
+       
+       $('#options .sub-ask-close').click(function() {
+               $('#options .sub-ask').hide();
+               
+               return false;
+       });
+       
+       $('#options .bottom .finish').click(function() {
+               if($(this).is('.save') && !$(this).hasClass('disabled'))
+                       return saveOptions();
+               if($(this).is('.cancel'))
+                       return closeOptions();
+               
+               return false;
+       });
+       
+       // The keyup events
+       $('#options .sub-ask input').keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // Microblog purge
+                       if($(this).is('.purge-microblog'))
+                               return purgeMyMicroblog();
+                       
+                       // Password change
+                       else if($(this).is('.password-change'))
+                               return sendNewPassword();
+                       
+                       // Account deletion
+                       else if($(this).is('.delete-account'))
+                               return deleteMyAccount();
+               }
+       });
+       
+       // Load the options
+       loadOptions();
+}
diff --git a/jappixmini/jappix/js/pep.js b/jappixmini/jappix/js/pep.js
new file mode 100644 (file)
index 0000000..04f9f15
--- /dev/null
@@ -0,0 +1,827 @@
+/*
+
+Jappix - An open social platform
+These are the PEP JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Stores the PEP items
+function storePEP(xid, type, value1, value2, value3, value4) {
+       // Handle the correct values
+       if(!value1)
+               value1 = '';
+       if(!value2)
+               value2 = '';
+       if(!value3)
+               value3 = '';
+       if(!value4)
+               value4 = '';
+       
+       // If one value
+       if(value1 || value2 || value3 || value4) {
+               // Define the XML variable
+               var xml = '<pep type="' + type + '">';
+               
+               // Generate the correct XML
+               if(type == 'tune')
+                       xml += '<artist>' + value1.htmlEnc() + '</artist><title>' + value2.htmlEnc() + '</title><album>' + value3.htmlEnc() + '</album><uri>' + value4.htmlEnc() + '</uri>';
+               else if(type == 'geoloc')
+                       xml += '<lat>' + value1.htmlEnc() + '</lat><lon>' + value2.htmlEnc() + '</lon><human>' + value3.htmlEnc() + '</human>';
+               else
+                       xml += '<value>' + value1.htmlEnc() + '</value><text>' + value2.htmlEnc() + '</text>';
+               
+               // End the XML node
+               xml += '</pep>';
+               
+               // Update the input with the new value
+               setDB('pep-' + type, xid, xml);
+       }
+       
+       else
+               removeDB('pep-' + type, xid);
+       
+       // Display the PEP event
+       displayPEP(xid, type);
+}
+
+// Displays a PEP item
+function displayPEP(xid, type) {
+       // Read the target input for values
+       var value = $(XMLFromString(getDB('pep-' + type, xid)));
+       var dText;
+       var aLink = ''
+       
+       // If the PEP element exists
+       if(type) {
+               // Get the user hash
+               var hash = hex_md5(xid);
+               
+               // Initialize
+               var fText, fValue;
+               var dText = '';
+               
+               // Parse the XML for mood and activity
+               if((type == 'mood') || (type == 'activity')) {
+                       if(value) {
+                               var pepValue = value.find('value').text();
+                               var pepText = value.find('text').text();
+                               
+                               // No value?
+                               if(!pepValue)
+                                       pepValue = 'none';
+                               
+                               // Apply the good values
+                               if(type == 'mood')
+                                       fValue = moodIcon(pepValue);
+                               else if(type == 'activity')
+                                       fValue = activityIcon(pepValue);
+                               if(!pepText)
+                                       fText = _e("unknown");
+                               else
+                                       fText = pepText;
+                       }
+                       
+                       else {
+                               if(type == 'mood')
+                                       fValue = moodIcon('undefined');
+                               else if(type == 'activity')
+                                       fValue = activityIcon('exercising');
+                               
+                               fText = _e("unknown");
+                       }
+                       
+                       dText = fText;
+                       fText = fText.htmlEnc();
+               }
+               
+               else if(type == 'tune') {
+                       fValue = 'tune-note';
+                       
+                       if(value) {
+                               // Parse the tune XML
+                               var tArtist = value.find('artist').text();
+                               var tTitle = value.find('title').text();
+                               var tAlbum = value.find('album').text();
+                               var tURI = value.find('uri').text();
+                               var fArtist, fTitle, fAlbum, fURI;
+                               
+                               // Apply the good values
+                               if(!tArtist && !tAlbum && !tTitle) {
+                                       fText = _e("unknown");
+                                       dText = fText;
+                               }
+                               
+                               else {
+                                       // URI element
+                                       if(!tURI)
+                                               fURI = 'http://grooveshark.com/search?q=' + encodeURIComponent(tArtist + ' ' + tTitle + ' ' + tAlbum);
+                                       else
+                                               fURI = tURI;
+                                       
+                                       // Artist element
+                                       if(!tArtist)
+                                               fArtist = _e("unknown");
+                                       else
+                                               fArtist = tArtist;
+                                       
+                                       // Title element
+                                       if(!tTitle)
+                                               fTitle = _e("unknown");
+                                       else
+                                               fTitle = tTitle;
+                                       
+                                       // Album element
+                                       if(!tAlbum)
+                                               fAlbum = _e("unknown");
+                                       else
+                                               fAlbum = tAlbum;
+                                       
+                                       // Generate the link to the title
+                                       aLink = ' href="' + fURI + '" target="_blank"';
+                                       
+                                       // Generate the text to be displayed
+                                       dText = fArtist + ' - ' + fTitle + ' (' + fAlbum + ')';
+                                       fText =  '<a' + aLink + '>' + dText + '</a>';
+                               }
+                       }
+                       
+                       else {
+                               fText = _e("unknown");
+                               dText = fText;
+                       }
+               }
+               
+               else if(type == 'geoloc') {
+                       fValue = 'location-world';
+                       
+                       if(value) {
+                               // Parse the geoloc XML
+                               var tLat = value.find('lat').text();
+                               var tLon = value.find('lon').text();
+                               var tHuman = value.find('human').text();
+                               var tReal = tHuman;
+                               
+                               // No human location?
+                               if(!tHuman)
+                                       tHuman = _e("See his/her position on the globe");
+                               
+                               // Generate the text to be displayed
+                               if(tLat && tLon) {
+                                       aLink = ' href="http://maps.google.com/?q=' + encodeQuotes(tLat) + ',' + encodeQuotes(tLon) + '" target="_blank"';
+                                       fText = '<a' + aLink + '>' + tHuman.htmlEnc() + '</a>';
+                                       
+                                       if(tReal)
+                                               dText = tReal;
+                                       else
+                                               dText = tLat + '; ' + tLon;
+                               }
+                               
+                               else {
+                                       fText = _e("unknown");
+                                       dText = fText;
+                               }
+                       }
+                       
+                       else {
+                               fText = _e("unknown");
+                               dText = fText;
+                       }
+               }
+               
+               // Apply the text to the buddy infos
+               var this_buddy = '#buddy-list .buddy[data-xid=' + escape(xid) + ']';
+               
+               if(exists(this_buddy))
+                       $(this_buddy + ' .bi-' + type).replaceWith('<p class="bi-' + type + ' talk-images ' + fValue + '" title="' + encodeQuotes(dText) + '">' + fText + '</p>');
+               
+               // Apply the text to the buddy chat
+               if(exists('#' + hash)) {
+                       // Selector
+                       var bc_pep = $('#' + hash + ' .bc-pep');
+                       
+                       // We remove the old PEP item
+                       bc_pep.find('a.bi-' + type).remove();
+                       
+                       // If the new PEP item is not null, create a new one
+                       if(fText != _e("unknown"))
+                               bc_pep.prepend(
+                                       '<a' + aLink + ' class="bi-' + type + ' talk-images ' + fValue + '" title="' + encodeQuotes(dText) + '"></a>'
+                               );
+                       
+                       // Process the new status position
+                       adaptChatPresence(hash);
+               }
+               
+               // If this is the PEP values of the logged in user
+               if(xid == getXID()) {
+                       // Change the icon/value of the target element
+                       if((type == 'mood') || (type == 'activity')) {
+                               // Change the input value
+                               var dVal = '';
+                               var dAttr = pepValue;
+                               
+                               // Must apply default values?
+                               if(pepValue == 'none') {
+                                       if(type == 'mood')
+                                               dAttr = 'happy';
+                                       else
+                                               dAttr = 'exercising';
+                               }
+                               
+                               // No text?
+                               if(dText != _e("unknown"))
+                                       dVal = dText;
+                               
+                               // Store this user event in our database
+                               setDB(type + '-value', 1, dAttr);
+                               setDB(type + '-text', 1, dVal);
+                               
+                               // Apply this PEP event
+                               $('#my-infos .f-' + type + ' a.picker').attr('data-value', dAttr);
+                               $('#my-infos .f-' + type + ' input').val(dVal);
+                               $('#my-infos .f-' + type + ' input').placeholder();
+                       }
+                       
+                       else if((type == 'tune') || (type == 'geoloc')) {
+                               // Reset the values
+                               $('#my-infos .f-others a.' + type).remove();
+                               
+                               // Not empty?
+                               if(dText != _e("unknown")) {
+                                       // Specific stuffs
+                                       var href, title, icon_class;
+                                       
+                                       if(type == 'tune') {
+                                               href = fURI;
+                                               title = dText;
+                                               icon_class = 'tune-note';
+                                       }
+                                       
+                                       else {
+                                               href = 'http://maps.google.com/?q=' + encodeQuotes(tLat) + ',' + encodeQuotes(tLon);
+                                               title = _e("Where are you?") + ' (' + dText + ')';
+                                               icon_class = 'location-world';
+                                       }
+                                       
+                                       // Must create the container?
+                                       if(!exists('#my-infos .f-others'))
+                                               $('#my-infos .content').append('<div class="element f-others"></div>');
+                                       
+                                       // Create the element
+                                       $('#my-infos .f-others').prepend(
+                                               '<a class="icon ' + type + '" href="' + encodeQuotes(href) + '" target="_blank" title="' + encodeQuotes(title) +  '">' + 
+                                                       '<span class="talk-images ' + icon_class + '"></span>' + 
+                                               '</a>'
+                                       );
+                               }
+                               
+                               // Empty?
+                               else if(!exists('#my-infos .f-others a.icon'))
+                                       $('#my-infos .f-others').remove();
+                               
+                               // Process the buddy-list height again
+                               adaptRoster();
+                       }
+               }
+       }
+}
+
+// Changes the mood icon
+function moodIcon(value) {
+       // The main var
+       var icon;
+       
+       // Switch the values
+       switch(value) {
+               case 'angry':
+               case 'cranky':
+               case 'hot':
+               case 'invincible':
+               case 'mean':
+               case 'restless':
+               case 'serious':
+               case 'strong':
+                       icon = 'mood-one';
+                       break;
+               
+               case 'contemplative':
+               case 'happy':
+               case 'playful':
+                       icon = 'mood-two';
+                       break;
+               
+               case 'aroused':
+               case 'envious':
+               case 'excited':
+               case 'interested':
+               case 'lucky':
+               case 'proud':
+               case 'relieved':
+               case 'satisfied':
+               case 'shy':
+                       icon = 'mood-three';
+                       break;
+               
+               case 'calm':
+               case 'cautious':
+               case 'contented':
+               case 'creative':
+               case 'humbled':
+               case 'lonely':
+               case 'undefined':
+               case 'none':
+                       icon = 'mood-four';
+                       break;
+               
+               case 'afraid':
+               case 'amazed':
+               case 'confused':
+               case 'dismayed':
+               case 'hungry':
+               case 'in_awe':
+               case 'indignant':
+               case 'jealous':
+               case 'lost':
+               case 'offended':
+               case 'outraged':
+               case 'shocked':
+               case 'surprised':
+               case 'embarrassed':
+               case 'impressed':
+                       icon = 'mood-five';
+                       break;
+               
+               case 'crazy':
+               case 'distracted':
+               case 'neutral':
+               case 'relaxed':
+               case 'thirsty':
+                       icon = 'mood-six';
+                       break;
+               
+               case 'amorous':
+               case 'curious':
+               case 'in_love':
+               case 'nervous':
+               case 'sarcastic':
+                       icon = 'mood-eight';
+                       break;
+               
+               case 'brave':
+               case 'confident':
+               case 'hopeful':
+               case 'grateful':
+               case 'spontaneous':
+               case 'thankful':
+                       icon = 'mood-nine';
+                       break;
+               
+               default:
+                       icon = 'mood-seven';
+                       break;
+       }
+       
+       // Return the good icon name
+       return icon;
+}
+
+// Changes the activity icon
+function activityIcon(value) {
+       // The main var
+       var icon;
+       
+       // Switch the values
+       switch(value) {
+               case 'doing_chores':
+                       icon = 'activity-doing_chores';
+                       break;
+               
+               case 'drinking':
+                       icon = 'activity-drinking';
+                       break;
+               
+               case 'eating':
+                       icon = 'activity-eating';
+                       break;
+               
+               case 'grooming':
+                       icon = 'activity-grooming';
+                       break;
+               
+               case 'having_appointment':
+                       icon = 'activity-having_appointment';
+                       break;
+               
+               case 'inactive':
+                       icon = 'activity-inactive';
+                       break;
+               
+               case 'relaxing':
+                       icon = 'activity-relaxing';
+                       break;
+               
+               case 'talking':
+                       icon = 'activity-talking';
+                       break;
+               
+               case 'traveling':
+                       icon = 'activity-traveling';
+                       break;
+               
+               case 'working':
+                       icon = 'activity-working';
+                       break;
+               default:
+                       icon = 'activity-exercising';
+                       break;
+       }
+       
+       // Return the good icon name
+       return icon;
+}
+
+// Sends the user's mood
+function sendMood(value, text) {
+       /* REF: http://xmpp.org/extensions/xep-0107.html */
+       
+       // We propagate the mood on the xmpp network
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // We create the XML document
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_MOOD, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+       var mood = item.appendChild(iq.buildNode('mood', {'xmlns': NS_MOOD}));
+       
+       if(value != 'none') {
+               mood.appendChild(iq.buildNode(value, {'xmlns': NS_MOOD}));
+               mood.appendChild(iq.buildNode('text', {'xmlns': NS_MOOD}, text));
+       }
+       
+       // And finally we send the mood that is set
+       con.send(iq);
+       
+       logThis('New mood sent: ' + value + ' (' + text + ')', 3);
+}
+
+// Sends the user's activity
+function sendActivity(main, sub, text) {
+       // We propagate the mood on the xmpp network
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // We create the XML document
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_ACTIVITY, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+       var activity = item.appendChild(iq.buildNode('activity', {'xmlns': NS_ACTIVITY}));
+       
+       if(main != 'none') {
+               var mainType = activity.appendChild(iq.buildNode(main, {'xmlns': NS_ACTIVITY}));
+               
+               // Child nodes
+               if(sub)
+                       mainType.appendChild(iq.buildNode(sub, {'xmlns': NS_ACTIVITY}));
+               if(text)
+                       activity.appendChild(iq.buildNode('text', {'xmlns': NS_ACTIVITY}, text));
+       }
+       
+       // And finally we send the mood that is set
+       con.send(iq);
+       
+       logThis('New activity sent: ' + main + ' (' + text + ')', 3);
+}
+
+// Sends the user's geographic position
+function sendPosition(vLat, vLon, vAlt, vCountry, vCountrycode, vRegion, vPostalcode, vLocality, vStreet, vBuilding, vText, vURI) {
+       /* REF: http://xmpp.org/extensions/xep-0080.html */
+       
+       // We propagate the position on pubsub
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // We create the XML document
+       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_GEOLOC, 'xmlns': NS_PUBSUB}));
+       var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+       var geoloc = item.appendChild(iq.buildNode('geoloc', {'xmlns': NS_GEOLOC}));
+       
+       // Create two position arrays
+       var pos_names  = ['lat', 'lon', 'alt', 'country', 'countrycode', 'region', 'postalcode', 'locality', 'street', 'building', 'text', 'uri', 'timestamp'];
+       var pos_values = [ vLat,  vLon,  vAlt,  vCountry,  vCountrycode,  vRegion,  vPostalcode,  vLocality,  vStreet,  vBuilding,  vText,  vURI,  getXMPPTime('utc')];
+       
+       for(var i = 0; i < pos_names.length; i++) {
+               if(pos_names[i] && pos_values[i])
+                       geoloc.appendChild(iq.buildNode(pos_names[i], {'xmlns': NS_GEOLOC}, pos_values[i]));
+       }
+       
+       // And finally we send the XML
+       con.send(iq);
+       
+       // For logger
+       if(vLat && vLon)
+               logThis('Geolocated.', 3);
+       else
+               logThis('Not geolocated.', 2);
+}
+
+// Parses the user's geographic position
+function parsePosition(data) {
+       var result = $(data).find('result:first');
+       
+       // Get latitude and longitude
+       var lat = result.find('geometry:first location:first lat').text();
+       var lng = result.find('geometry:first location:first lng').text();
+       
+       var array = [
+                    lat,
+                    lng,
+                    result.find('address_component:has(type:contains("country")):first long_name').text(),
+                    result.find('address_component:has(type:contains("country")):first short_name').text(),
+                    result.find('address_component:has(type:contains("administrative_area_level_1")):first long_name').text(),
+                    result.find('address_component:has(type:contains("postal_code")):first long_name').text(),
+                    result.find('address_component:has(type:contains("locality")):first long_name').text(),
+                    result.find('address_component:has(type:contains("route")):first long_name').text(),
+                    result.find('address_component:has(type:contains("street_number")):first long_name').text(),
+                    result.find('formatted_address:first').text(),
+                    'http://maps.google.com/?q=' + encodeQuotes(lat) + ',' + encodeQuotes(lng)
+                   ];
+       
+       return array;
+}
+
+// Converts a position into an human-readable one
+function humanPosition(tLocality, tRegion, tCountry) {
+       var tHuman = '';
+       
+       // Any locality?
+       if(tLocality) {
+               tHuman += tLocality;
+               
+               if(tRegion)
+                       tHuman += ', ' + tRegion;
+               if(tCountry)
+                       tHuman += ', ' + tCountry;
+       }
+       
+       // Any region?
+       else if(tRegion) {
+               tHuman += tRegion;
+               
+               if(tCountry)
+                       tHuman += ', ' + tCountry;
+       }
+       
+       // Any country?
+       else if(tCountry)
+               tHuman += tCountry;
+       
+       return tHuman;
+}
+
+// Gets the user's geographic position
+function getPosition(position) {
+       // Convert integers to strings
+       var vLat = '' + position.coords.latitude;
+       var vLon = '' + position.coords.longitude;
+       var vAlt = '' + position.coords.altitude;
+       
+       // Get full position (from Google Maps API)
+       $.get('./php/geolocation.php', {latitude: vLat, longitude: vLon, language: XML_LANG}, function(data) {
+               // Parse data!
+               var results = parsePosition(data);
+               
+               // Handled!
+               sendPosition(
+                            vLat,
+                            vLon,
+                            vAlt,
+                            results[2],
+                            results[3],
+                            results[4],
+                            results[5],
+                            results[6],
+                            results[7],
+                            results[8],
+                            results[9],
+                            results[10]
+                           );
+               
+               // Store data
+               setDB('geolocation', 'now', xmlToString(data));
+               
+               logThis('Position details got from Google Maps API.');
+       });
+       
+       logThis('Position got: latitude > ' + vLat + ' / longitude > ' + vLon + ' / altitude > ' + vAlt);
+}
+
+// Geolocates the user
+function geolocate() {
+       // Don't fire it until options & features are not retrieved!
+       if(!getDB('options', 'geolocation') || (getDB('options', 'geolocation') == '0') || !enabledPEP())
+               return;
+       
+       // We publish the user location if allowed
+       if(navigator.geolocation) {
+               // Wait a bit... (to fix a bug)
+               $('#my-infos').stopTime().oneTime('1s', function() {
+                       navigator.geolocation.getCurrentPosition(getPosition);
+               });
+               
+               logThis('Geolocating...', 3);
+       }
+       
+       // Any error?
+       else
+               logThis('Not geolocated: browser does not support it.', 1);
+}
+
+// Displays all the supported PEP events for a given XID
+function displayAllPEP(xid) {
+       displayPEP(xid, 'mood');
+       displayPEP(xid, 'activity');
+       displayPEP(xid, 'tune');
+       displayPEP(xid, 'geoloc');
+}
+
+// Plugin launcher
+function launchPEP() {
+       // Apply empty values to the PEP database
+       setDB('mood-value', 1, '');
+       setDB('mood-text', 1, '');
+       setDB('activity-value', 1, '');
+       setDB('activity-text', 1, '');
+       
+       // Click event for user mood
+       $('#my-infos .f-mood a.picker').click(function() {
+               // Initialize some vars
+               var path = '#my-infos .f-mood div.bubble';
+               var mood_id = ['crazy', 'excited', 'playful', 'happy', 'shocked', 'hot', 'sad', 'amorous', 'confident'];
+               var mood_lang = [_e("Crazy"), _e("Excited"), _e("Playful"), _e("Happy"), _e("Shocked"), _e("Hot"), _e("Sad"), _e("Amorous"), _e("Confident")];
+               var mood_val = $('#my-infos .f-mood a.picker').attr('data-value');
+               
+               // Yet displayed?
+               var can_append = true;
+               
+               if(exists(path))
+                       can_append = false;
+               
+               // Add this bubble!
+               showBubble(path);
+               
+               if(!can_append)
+                       return false;
+               
+               // Generate the HTML code
+               var html = '<div class="bubble removable">';
+               
+               for(i in mood_id) {
+                       // Yet in use: no need to display it!
+                       if(mood_id[i] == mood_val)
+                               continue;
+                       
+                       html += '<a href="#" class="talk-images" data-value="' + mood_id[i] + '" title="' + mood_lang[i] + '"></a>';
+               }
+               
+               html += '</div>';
+               
+               // Append the HTML code
+               $('#my-infos .f-mood').append(html);
+               
+               // Click event
+               $(path + ' a').click(function() {
+                       // Update the mood marker
+                       $('#my-infos .f-mood a.picker').attr('data-value', $(this).attr('data-value'));
+                       
+                       // Close the bubble
+                       closeBubbles();
+                       
+                       // Focus on the status input
+                       $(document).oneTime(10, function() {
+                               $('#mood-text').focus();
+                       });
+                       
+                       return false;
+               });
+               
+               return false;
+       });
+       
+       // Click event for user activity
+       $('#my-infos .f-activity a.picker').click(function() {
+               // Initialize some vars
+               var path = '#my-infos .f-activity div.bubble';
+               var activity_id = ['doing_chores', 'drinking', 'eating', 'exercising', 'grooming', 'having_appointment', 'inactive', 'relaxing', 'talking', 'traveling', 'working'];
+               var activity_lang = [_e("Chores"), _e("Drinking"), _e("Eating"), _e("Exercising"), _e("Grooming"), _e("Appointment"), _e("Inactive"), _e("Relaxing"), _e("Talking"), _e("Traveling"), _e("Working")];
+               var activity_val = $('#my-infos .f-activity a.picker').attr('data-value');
+               
+               // Yet displayed?
+               var can_append = true;
+               
+               if(exists(path))
+                       can_append = false;
+               
+               // Add this bubble!
+               showBubble(path);
+               
+               if(!can_append)
+                       return false;
+               
+               // Generate the HTML code
+               var html = '<div class="bubble removable">';
+               
+               for(i in activity_id) {
+                       // Yet in use: no need to display it!
+                       if(activity_id[i] == activity_val)
+                               continue;
+                       
+                       html += '<a href="#" class="talk-images" data-value="' + activity_id[i] + '" title="' + activity_lang[i] + '"></a>';
+               }
+               
+               html += '</div>';
+               
+               // Append the HTML code
+               $('#my-infos .f-activity').append(html);
+               
+               // Click event
+               $(path + ' a').click(function() {
+                       // Update the activity marker
+                       $('#my-infos .f-activity a.picker').attr('data-value', $(this).attr('data-value'));
+                       
+                       // Close the bubble
+                       closeBubbles();
+                       
+                       // Focus on the status input
+                       $(document).oneTime(10, function() {
+                               $('#activity-text').focus();
+                       });
+                       
+                       return false;
+               });
+               
+               return false;
+       });
+       
+       // Submit events for PEP inputs
+       $('#mood-text, #activity-text').placeholder()
+       
+       .keyup(function(e) {
+               if(e.keyCode == 13) {
+                       $(this).blur();
+                       
+                       return false;
+               }
+       });
+       
+       // Input blur handler
+       $('#mood-text').blur(function() {
+               // Read the parameters
+               var value = $('#my-infos .f-mood a.picker').attr('data-value');
+               var text = $(this).val();
+               
+               // Must send the mood?
+               if((value != getDB('mood-value', 1)) || (text != getDB('mood-text', 1))) {
+                       // Update the local stored values
+                       setDB('mood-value', 1, value);
+                       setDB('mood-text', 1, text);
+                       
+                       // Send it!
+                       sendMood(value, text);
+               }
+       })
+       
+       // Input focus handler
+       .focus(function() {
+               closeBubbles();
+       });
+       
+       // Input blur handler
+       $('#activity-text').blur(function() {
+               // Read the parameters
+               var value = $('#my-infos .f-activity a.picker').attr('data-value');
+               var text = $(this).val();
+               
+               // Must send the activity?
+               if((value != getDB('activity-value', 1)) || (text != getDB('activity-text', 1))) {
+                       // Update the local stored values
+                       setDB('activity-value', 1, value);
+                       setDB('activity-text', 1, text);
+                       
+                       // Send it!
+                       sendActivity(value, '', text);
+               }
+       })
+       
+       // Input focus handler
+       .focus(function() {
+               closeBubbles();
+       });
+}
diff --git a/jappixmini/jappix/js/popup.js b/jappixmini/jappix/js/popup.js
new file mode 100644 (file)
index 0000000..0d799cc
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+
+Jappix - An open social platform
+These are the popup JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/04/11
+
+*/
+
+// Creates a popup code
+function createPopup(id, content) {
+       // Popup exists?
+       if(exists('#' + id))
+               return false;
+       
+       // Append the popup code
+       $('body').append(
+               '<div id="' + id + '" class="lock removable">' + 
+                       '<div class="popup">' + 
+                               content + 
+                       '</div>' + 
+               '</div>'
+       );
+       
+       return true;
+}
+
+// Destroys a popup code
+function destroyPopup(id) {
+       // Stop the popup timers
+       $('#' + id + ' *').stopTime();
+       
+       // Remove the popup
+       $('#' + id).remove();
+       
+       // Manage input focus
+       inputFocus();
+}
diff --git a/jappixmini/jappix/js/presence.js b/jappixmini/jappix/js/presence.js
new file mode 100644 (file)
index 0000000..0834209
--- /dev/null
@@ -0,0 +1,1075 @@
+/*
+
+Jappix - An open social platform
+These are the presence JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/09/11
+
+*/
+
+// Sends the user first presence
+var FIRST_PRESENCE_SENT = false;
+
+function firstPresence(checksum) {
+       logThis('First presence sent.', 3);
+       
+       // Jappix is now ready: change the title
+       pageTitle('talk');
+       
+       // Anonymous check
+       var is_anonymous = isAnonymous();
+       
+       // Update our marker
+       FIRST_PRESENCE_SENT = true;
+       
+       // Try to use the last status message
+       var status = getDB('options', 'presence-status');
+       
+       if(!status)
+               status = '';
+       
+       // We tell the world that we are online
+       if(!is_anonymous)
+               sendPresence('', '', '', status, checksum);
+       
+       // Any status to apply?
+       if(status)
+               $('#presence-status').val(status);
+       
+       // Enable the presence picker
+       $('#presence-status').removeAttr('disabled');
+       $('#my-infos .f-presence a.picker').removeClass('disabled');
+       
+       // We set the last activity stamp
+       PRESENCE_LAST_ACTIVITY = getTimeStamp();
+       
+       // We store our presence
+       setDB('presence-show', 1, 'available');
+       
+       // Not anonymous
+       if(!is_anonymous) {
+               // We get the stored bookmarks (because of the photo hash and some other stuffs, we must get it later)
+               getStorage(NS_BOOKMARKS);
+               
+               // We open a new chat if a XMPP link was submitted
+               if((parent.location.hash != '#OK') && LINK_VARS['x']) {
+                       // A link is submitted in the URL
+                       xmppLink(LINK_VARS['x']);
+                       
+                       // Set a OK status
+                       parent.location.hash = 'OK';
+               }
+       }
+}
+
+// Handles incoming presence packets
+function handlePresence(presence) {
+       // We define everything needed here
+       var from = fullXID(getStanzaFrom(presence));
+       var hash = hex_md5(from);
+       var node = presence.getNode();
+       var xid = bareXID(from);
+       var xidHash = hex_md5(xid);
+       
+       // We get the type content
+       var type = presence.getType();
+       if(!type)
+               type = '';
+       
+       // We get the priority content
+       var priority = presence.getPriority() + '';
+       if(!priority || (type == 'error'))
+               priority = '0';
+       
+       // We get the show content
+       var show = presence.getShow();
+       if(!show || (type == 'error'))
+               show = '';
+       
+       // We get the status content
+       var status = presence.getStatus();
+       if(!status || (type == 'error'))
+               status = '';
+       
+       // We get the photo content
+       var photo = $(node).find('x[xmlns=' + NS_VCARD_P + ']:first photo');
+       var checksum = photo.text();
+       var hasPhoto = photo.size();
+       
+       if(hasPhoto && (type != 'error'))
+               hasPhoto = 'true';
+       else
+               hasPhoto = 'false';
+       
+       // We get the CAPS content
+       var caps = $(node).find('c[xmlns=' + NS_CAPS + ']:first').attr('ver');
+       if(!caps || (type == 'error'))
+               caps = '';
+       
+       // This presence comes from another resource of my account with a difference avatar checksum
+       if((xid == getXID()) && (hasPhoto == 'true') && (checksum != getDB('checksum', 1)))
+               getAvatar(getXID(), 'force', 'true', 'forget');
+       
+       // This presence comes from a groupchat
+       if(isPrivate(xid)) {
+               var x_muc = $(node).find('x[xmlns=' + NS_MUC_USER + ']:first');
+               var item = x_muc.find('item');
+               var affiliation = item.attr('affiliation');
+               var role = item.attr('role');
+               var reason = item.find('reason').text();
+               var iXID = item.attr('jid');
+               var iNick = item.attr('nick');
+               var nick = thisResource(from);
+               var messageTime = getCompleteTime();
+               var notInitial = true;
+               
+               // Read the status code
+               var status_code = new Array();
+               
+               x_muc.find('status').each(function() {
+                       status_code.push(parseInt($(this).attr('code')));
+               });
+               
+               // If this is an initial presence (when user join the room)
+               if(exists('#' + xidHash + '[data-initial=true]'))
+                       notInitial = false;
+               
+               // If one user is quitting
+               if(type && (type == 'unavailable')) {
+                       displayMucPresence(from, xidHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, notInitial);
+                       
+                       removeDB('presence', from);
+               }
+               
+               // If one user is joining
+               else {
+                       // Fixes M-Link first presence bug (missing ID!)
+                       if((nick == getMUCNick(xidHash)) && (presence.getID() == null) && !exists('#page-engine #' + xidHash + ' .list .' + hash)) {
+                               handleMUC(presence);
+                               
+                               logThis('Passed M-Link MUC first presence handling.', 2);
+                       }
+                       
+                       else {
+                               displayMucPresence(from, xidHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, notInitial);
+                               
+                               var xml = '<presence from="' + encodeQuotes(from) + '"><priority>' + priority.htmlEnc() + '</priority><show>' + show.htmlEnc() + '</show><type>' + type.htmlEnc() + '</type><status>' + status.htmlEnc() + '</status><avatar>' + hasPhoto.htmlEnc() + '</avatar><checksum>' + checksum.htmlEnc() + '</checksum><caps>' + caps.htmlEnc() + '</caps></presence>';
+                               
+                               setDB('presence', from, xml);
+                       }
+               }
+               
+               // Manage the presence
+               presenceFunnel(from, hash);
+       }
+       
+       // This presence comes from an user or a gateway
+       else {
+               // Subscribed & unsubscribed stanzas
+               if((type == 'subscribed') || (type == 'unsubscribed'))
+                       return;
+               
+               // Subscribe stanza
+               else if(type == 'subscribe') {
+                       // This is a buddy we can safely authorize, because we added him to our roster
+                       if(exists('#buddy-list .buddy[data-xid=' + escape(xid) + ']'))
+                               acceptSubscribe(xid);
+                       
+                       // We do not know this entity, we'd be better ask the user
+                       else {
+                               // Get the nickname
+                               var nickname = $(node).find('nick[xmlns=' + NS_NICK + ']:first').text();
+                               
+                               // New notification
+                               newNotification('subscribe', xid, [xid, nickname], status);
+                       }
+               }
+               
+               // Unsubscribe stanza
+               else if(type == 'unsubscribe')
+                       sendRoster(xid, 'remove');
+               
+               // Other stanzas
+               else {
+                       // Unavailable/error presence
+                       if(type == 'unavailable')
+                               removeDB('presence', from);
+                       
+                       // Other presence (available, subscribe...)
+                       else {
+                               var xml = '<presence from="' + encodeQuotes(from) + '"><priority>' + priority.htmlEnc() + '</priority><show>' + show.htmlEnc() + '</show><type>' + type.htmlEnc() + '</type><status>' + status.htmlEnc() + '</status><avatar>' + hasPhoto.htmlEnc() + '</avatar><checksum>' + checksum.htmlEnc() + '</checksum><caps>' + caps.htmlEnc() + '</caps></presence>';
+                               
+                               setDB('presence', from, xml);
+                       }
+                       
+                       // We manage the presence
+                       presenceFunnel(xid, xidHash);
+                       
+                       // We display the presence in the current chat
+                       if(exists('#' + xidHash)) {
+                               var dStatus = filterStatus(xid, status, false);
+                               
+                               if(dStatus)
+                                       dStatus = ' (' + dStatus + ')';
+                               
+                               // Generate the presence-in-chat code
+                               var dName = getBuddyName(from).htmlEnc();
+                               var dBody = dName + ' (' + from + ') ' + _e("is now") + ' ' + humanShow(show, type) + dStatus;
+                               
+                               // Check whether it has been previously displayed
+                               var can_display = true;
+                               
+                               if($('#' + xidHash + ' .one-line.system-message:last').html() == dBody)
+                                       can_display = false;
+                               
+                               if(can_display)
+                                       displayMessage('chat', xid, xidHash, dName, dBody, getCompleteTime(), getTimeStamp(), 'system-message', false);
+                       }
+               }
+       }
+       
+       // For logger
+       if(!show) {
+               if(!type)
+                       show = 'available';
+               else
+                       show = 'unavailable';
+       }
+       
+       logThis('Presence received: ' + show + ', from ' + from);
+}
+
+// Displays a MUC presence
+function displayMucPresence(from, roomHash, hash, type, show, status, affiliation, role, reason, status_code, iXID, iNick, messageTime, nick, initial) {
+       // Generate the values
+       var thisUser = '#page-engine #' + roomHash + ' .list .' + hash;
+       var thisPrivate = $('#' + hash + ' .message-area');
+       var nick_html = nick.htmlEnc();
+       var real_xid = '';
+       var write = nick_html + ' ';
+       var notify = false;
+       
+       // Reset data?
+       if(!role)
+               role = 'participant';
+       if(!affiliation)
+               affiliation = 'none';
+       
+       // Must update the role?
+       if(exists(thisUser) && (($(thisUser).attr('data-role') != role) || ($(thisUser).attr('data-affiliation') != affiliation)))
+               $(thisUser).remove();
+       
+       // Any XID submitted?
+       if(iXID) {
+               real_xid = ' data-realxid="' + iXID + '"';
+               iXID = bareXID(iXID);
+               write += ' (<a onclick="return checkChatCreate(\'' + encodeOnclick(iXID) + '\', \'chat\');" href="xmpp:' + encodeOnclick(iXID) + '">' + iXID + '</a>) ';
+       }
+       
+       // User does not exists yet
+       if(!exists(thisUser) && (!type || (type == 'available'))) {
+               var myself = '';
+               
+               // Is it me?
+               if(nick == getMUCNick(roomHash)) {
+                       // Enable the room
+                       $('#' + roomHash + ' .message-area').removeAttr('disabled');
+                       
+                       // Marker
+                       myself = ' myself';
+               }
+               
+               // Set the user in the MUC list
+               $('#' + roomHash + ' .list .' + role + ' .title').after(
+                       '<div class="user ' + hash + myself + '" data-xid="' + encodeQuotes(from) + '" data-nick="' + escape(nick) + '"' + real_xid + ' data-role="' + encodeQuotes(role) + '" data-affiliation="' + encodeQuotes(affiliation) + '">' + 
+                               '<div class="name talk-images available">' + nick_html + '</div>' + 
+                               
+                               '<div class="avatar-container">' + 
+                                       '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                               '</div>' + 
+                       '</div>'
+               );
+               
+               // Click event
+               if(nick != getMUCNick(roomHash))
+                       $(thisUser).live('click', function() {
+                               checkChatCreate(from, 'private');
+                       });
+               
+               // We tell the user that someone entered the room
+               if(!initial) {
+                       notify = true;
+                       write += _e("joined the chat room");
+                       
+                       // Any status?
+                       if(status)
+                               write += ' (' + filterThisMessage(status, nick_html, true) + ')';
+                       else
+                               write += ' (' + _e("no status") + ')';
+               }
+               
+               // Enable the private chat input
+               thisPrivate.removeAttr('disabled');
+       }
+       
+       else if((type == 'unavailable') || (type == 'error')) {
+               // Is it me?
+               if(nick == getMUCNick(roomHash)) {
+                       $(thisUser).remove();
+                       
+                       // Disable the groupchat input
+                       $('#' + roomHash + ' .message-area').attr('disabled', true);
+                       
+                       // Remove all the groupchat users
+                       $('#' + roomHash + ' .list .user').remove();
+               }
+               
+               // Someone has been kicked or banned?
+               if(existArrayValue(status_code, 301) || existArrayValue(status_code, 307)) {
+                       $(thisUser).remove();
+                       notify = true;
+                       
+                       // Kicked?
+                       if(existArrayValue(status_code, 307))
+                               write += _e("has been kicked");
+                       
+                       // Banned?
+                       if(existArrayValue(status_code, 301))
+                               write += _e("has been banned");
+                       
+                       // Any reason?
+                       if(reason)
+                               write += ' (' + filterThisMessage(reason, nick_html, true) + ')';
+                       else
+                               write += ' (' + _e("no reason") + ')';
+               }
+               
+               // Nickname change?
+               else if(existArrayValue(status_code, 303) && iNick) {
+                       notify = true;
+                       write += printf(_e("changed his/her nickname to %s"), iNick.htmlEnc());
+                       
+                       // New values
+                       var new_xid = cutResource(from) + '/' + iNick;
+                       var new_hash = hex_md5(new_xid);
+                       var new_class = 'user ' + new_hash;
+                       
+                       if($(thisUser).hasClass('myself'))
+                               new_class += ' myself';
+                       
+                       // Die the click event
+                       $(thisUser).die('click');
+                       
+                       // Change to the new nickname
+                       $(thisUser).attr('data-nick', iNick)
+                                  .attr('data-xid', new_xid)
+                                  .find('.name').text(iNick);
+                       
+                       // Change the user class
+                       $(thisUser).attr('class', new_class);
+                       
+                       // New click event
+                       $('#page-engine #' + roomHash + ' .list .' + new_hash).live('click', function() {
+                               checkChatCreate(new_xid, 'private');
+                       });
+               }
+               
+               // We tell the user that someone left the room
+               else if(!initial) {
+                       $(thisUser).remove();
+                       notify = true;
+                       write += _e("left the chat room");
+                       
+                       // Any status?
+                       if(status)
+                               write += ' (' + filterThisMessage(status, nick_html, true) + ')';
+                       else
+                               write += ' (' + _e("no status") + ')';
+               }
+               
+               // Disable the private chat input
+               thisPrivate.attr('disabled', true);
+       }
+       
+       // Must notify something
+       if(notify)
+               displayMessage('groupchat', from, roomHash, nick_html, write, messageTime, getTimeStamp(), 'system-message', false);
+       
+       // Set the good status show icon
+       switch(show) {
+               case 'chat':
+               case 'away':
+               case 'xa':
+               case 'dnd':
+                       break;
+               
+               default:
+                       show = 'available';
+                       break;
+       }
+       
+       $(thisUser + ' .name').attr('class', 'name talk-images ' + show);
+       
+       // Set the good status text
+       var uTitle = nick;
+       
+       // Any XID to add?
+       if(iXID)
+               uTitle += ' (' + iXID + ')';
+       
+       // Any status to add?
+       if(status)
+               uTitle += ' - ' + status;
+       
+       $(thisUser).attr('title', uTitle);
+       
+       // Show or hide the role category, depending of its content
+       $('#' + roomHash + ' .list .role').each(function() {
+               if($(this).find('.user').size())
+                       $(this).show();
+               else
+                       $(this).hide();
+       });
+}
+
+// Filters a given status
+function filterStatus(xid, status, cut) {
+       var dStatus = '';
+       
+       if(!status)
+               status = '';
+       
+       else {
+               if(cut)
+                       dStatus = truncate(status, 50);
+               else
+                       dStatus = status;
+               
+               dStatus = filterThisMessage(dStatus, getBuddyName(xid).htmlEnc(), true);
+       }
+       
+       return dStatus;
+}
+
+// Displays a user's presence
+function displayPresence(value, type, show, status, hash, xid, avatar, checksum, caps) {
+       // Display the presence in the roster
+       var path = '#buddy-list .' + hash;
+       var buddy = $('#buddy-list .content .' + hash);
+       var dStatus = filterStatus(xid, status, false);
+       var tStatus = encodeQuotes(status);
+       var biStatus;
+       
+       // The buddy presence behind his name
+       $(path + ' .name .buddy-presence').replaceWith('<p class="buddy-presence talk-images ' + type + '">' + value + '</p>');
+       
+       // The buddy presence in the buddy infos
+       if(dStatus)
+               biStatus = dStatus;
+       else
+               biStatus = value;
+       
+       $(path + ' .bi-status').replaceWith('<p class="bi-status talk-images ' + type + '" title="' + tStatus + '">' + biStatus + '</p>');
+       
+       // When the buddy disconnect himself, we hide him
+       if((type == 'unavailable') || (type == 'error')) {
+               // Set a special class to the buddy
+               buddy.addClass('hidden-buddy');
+               
+               // No filtering is launched?
+               if(!SEARCH_FILTERED)
+                       buddy.hide();
+               
+               // All the buddies are shown?
+               if(BLIST_ALL)
+                       buddy.show();
+               
+               // Chat stuffs
+               if(exists('#' + hash)) {
+                       // Remove the chatstate stuffs
+                       resetChatState(hash);
+                       $('#' + hash + ' .chatstate').remove();
+                       $('#' + hash + ' .message-area').removeAttr('data-chatstates');
+                       
+                       // Get the buddy avatar (only if a chat is opened)
+                       getAvatar(xid, 'cache', 'true', 'forget');
+               }
+       }
+       
+       // If the buddy is online
+       else {
+               // When the buddy is online, we show it
+               buddy.removeClass('hidden-buddy');
+               
+               // No filtering is launched?
+               if(!SEARCH_FILTERED)
+                       buddy.show();
+               
+               // Get the online buddy avatar if not a gateway
+               getAvatar(xid, 'cache', avatar, checksum);
+       }
+       
+       // Display the presence in the chat
+       if(exists('#' + hash)) {
+               // We generate a well formed status message
+               if(dStatus) {
+                       // No need to write the same status two times
+                       if(dStatus == value)
+                               dStatus = '';
+                       else
+                               dStatus = ' (' + dStatus + ')';
+               }
+               
+               // We show the presence value
+               $('#' + hash + ' .bc-infos').replaceWith('<p class="bc-infos" title="' + tStatus + '"><span class="' + type + ' show talk-images">' + value + '</span>' + dStatus + '</p>');
+               
+               // Process the new status position
+               adaptChatPresence(hash);
+               
+               // Get the disco#infos for this user
+               var highest = getHighestResource(xid);
+               
+               if(highest)
+                       getDiscoInfos(highest, caps);
+               else
+                       displayDiscoInfos(xid, '');
+       }
+       
+       // Display the presence in the switcher
+       if(exists('#page-switch .' + hash))
+               $('#page-switch .' + hash + ' .icon').removeClass('available unavailable error away busy').addClass(type);
+       
+       // Update roster groups
+       if(!SEARCH_FILTERED)
+               updateGroups();
+       else
+               funnelFilterBuddySearch();
+}
+
+// Process the chat presence position
+function adaptChatPresence(hash) {
+       // Get values
+       var pep_numb = $('#' + hash + ' .bc-pep').find('a').size();
+       
+       // Process the right position
+       var presence_right = 12;
+       
+       if(pep_numb)
+               presence_right = (pep_numb * 20) + 18;
+       
+       // Apply the right position
+       $('#' + hash + ' p.bc-infos').css('right', presence_right);
+}
+
+// Convert the presence "show" element into a human-readable output
+function humanShow(show, type) {
+       if(type == 'unavailable')
+               show = _e("Unavailable");
+       
+       else if(type == 'error')
+               show = _e("Error");
+       
+       else {
+               switch(show) {
+                       case 'chat':
+                               show = _e("Talkative");
+                               break;
+                       
+                       case 'away':
+                               show = _e("Away");
+                               break;
+                       
+                       case 'xa':
+                               show = _e("Not available");
+                               break;
+                       
+                       case 'dnd':
+                               show = _e("Busy");
+                               break;
+                       
+                       default:
+                               show = _e("Available");
+                               break;
+               }
+       }
+       
+       return show;
+}
+
+// Makes the presence data go in the right way
+function presenceIA(type, show, status, hash, xid, avatar, checksum, caps) {
+       // Is there a status defined?
+       if(!status)
+               status = humanShow(show, type);
+       
+       // Then we can handle the events
+       if(type == 'error')
+               displayPresence(_e("Error"), 'error', show, status, hash, xid, avatar, checksum, caps);
+       
+       else if(type == 'unavailable')
+               displayPresence(_e("Unavailable"), 'unavailable', show, status, hash, xid, avatar, checksum, caps);
+       
+       else {
+               switch(show) {
+                       case 'chat':
+                               displayPresence(_e("Talkative"), 'available', show, status, hash, xid, avatar, checksum, caps);
+                               break;
+                       
+                       case 'away':
+                               displayPresence(_e("Away"), 'away', show, status, hash, xid, avatar, checksum, caps);
+                               break;
+                       
+                       case 'xa':
+                               displayPresence(_e("Not available"), 'busy', show, status, hash, xid, avatar, checksum, caps);
+                               break;
+                       
+                       case 'dnd':
+                               displayPresence(_e("Busy"), 'busy', show, status, hash, xid, avatar, checksum, caps);
+                               break;
+                       
+                       default:
+                               displayPresence(_e("Available"), 'available', show, status, hash, xid, avatar, checksum, caps);
+                               break;
+               }
+       }
+}
+
+// Gets the highest resource priority for an user
+function highestPriority(xid) {
+       var maximum = null;
+       var selector, priority, type, highest;
+       
+       // This is a groupchat presence
+       if(xid.indexOf('/') != -1)
+               highest = XMLFromString(getDB('presence', xid));
+       
+       // This is a "normal" presence: get the highest priority resource
+       else {
+               for(var i = 0; i < sessionStorage.length; i++) {
+                       // Get the pointer values
+                       var current = sessionStorage.key(i);
+                       
+                       // If the pointer is on a stored presence
+                       if(explodeThis('_', current, 0) == 'presence') {
+                               // Get the current XID
+                               var now = bareXID(explodeThis('_', current, 1));
+                               
+                               // If the current XID equals the asked XID
+                               if(now == xid) {
+                                       var xml = XMLFromString(sessionStorage.getItem(current));
+                                       var priority = parseInt($(xml).find('priority').text());
+                                       
+                                       // Higher priority
+                                       if((priority >= maximum) || (maximum == null)) {
+                                               maximum = priority;
+                                               highest = xml;
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       // The user might be offline if no highest
+       if(!highest)
+               highest = XMLFromString('<presence><type>unavailable</type></presence>');
+       
+       return highest;
+}
+
+// Gets the resource from a XID which has the highest priority
+function getHighestResource(xid) {
+       var xml = $(highestPriority(xid));
+       var highest = xml.find('presence').attr('from');
+       var type = xml.find('type').text();
+       
+       // If the use is online, we can return its highest resource
+       if(!type || (type == 'available') || (type == 'null'))
+               return highest;
+       else
+               return false;
+}
+
+// Makes something easy to process for the presence IA
+function presenceFunnel(xid, hash) {
+       // Get the highest priority presence value
+       var xml = $(highestPriority(xid));
+       var type = xml.find('type').text();
+       var show = xml.find('show').text();
+       var status = xml.find('status').text();
+       var avatar = xml.find('avatar').text();
+       var checksum = xml.find('checksum').text();
+       var caps = xml.find('caps').text();
+       
+       // Display the presence with that stored value
+       if(!type && !show)
+               presenceIA('', 'available', status, hash, xid, avatar, checksum, caps);
+       else
+               presenceIA(type, show, status, hash, xid, avatar, checksum, caps);
+}
+
+// Sends a defined presence packet
+function sendPresence(to, type, show, status, checksum, limit_history, password, handle) {
+       // Get some stuffs
+       var priority = getDB('priority', 1);
+       
+       if(!priority)
+               priority = '1';
+       if(!checksum)
+               checksum = getDB('checksum', 1);
+       if(show == 'available')
+               show = '';
+       if(type == 'available')
+               type = '';
+       
+       // New presence
+       var presence = new JSJaCPresence();
+       
+       // Avoid "null" or "none" if nothing stored
+       if(!checksum || (checksum == 'none'))
+               checksum = '';
+       
+       // Presence headers
+       if(to)
+               presence.setTo(to);
+       if(type)
+               presence.setType(type);
+       if(show)
+               presence.setShow(show);
+       if(status)
+               presence.setStatus(status);
+       
+       presence.setPriority(priority);
+       
+       // CAPS (entity capabilities)
+       presence.appendNode('c', {'xmlns': NS_CAPS, 'hash': 'sha-1', 'node': 'https://www.jappix.com/', 'ver': myCaps()});
+       
+       // Nickname
+       var nickname = getName();
+       
+       if(nickname)
+               presence.appendNode('nick', {'xmlns': NS_NICK}, nickname);
+       
+       // vcard-temp:x:update node
+       var x = presence.appendNode('x', {'xmlns': NS_VCARD_P});
+       x.appendChild(presence.buildNode('photo', {'xmlns': NS_VCARD_P}, checksum));
+       
+       // MUC X data
+       if(limit_history || password) {
+               var xMUC = presence.appendNode('x', {'xmlns': NS_MUC});
+               
+               // Max messages age (for MUC)
+               if(limit_history)
+                       xMUC.appendChild(presence.buildNode('history', {'maxstanzas': 20, 'seconds': 86400, 'xmlns': NS_MUC}));
+               
+               // Room password
+               if(password)
+                       xMUC.appendChild(presence.buildNode('password', {'xmlns': NS_MUC}, password));
+       }
+       
+       // If away, send a last activity time
+       if((show == 'away') || (show == 'xa')) {
+               /* REF: http://xmpp.org/extensions/xep-0256.html */
+               
+               presence.appendNode(presence.buildNode('query', {
+                       'xmlns': NS_LAST,
+                       'seconds': getPresenceLast()
+               }));
+       }
+       
+       // Else, set a new last activity stamp
+       else
+               PRESENCE_LAST_ACTIVITY = getTimeStamp();
+       
+       // Send the presence packet
+       if(handle)
+               con.send(presence, handle);
+       else
+               con.send(presence);
+       
+       if(!type)
+               type = 'available';
+       
+       logThis('Presence sent: ' + type, 3);
+}
+
+// Performs all the actions to get the presence data
+function presenceSend(checksum, autoidle) {
+       // We get the values of the inputs
+       var show = getUserShow();
+       var status = getUserStatus();
+       
+       // Send the presence
+       if(!isAnonymous())
+               sendPresence('', '', show, status, checksum);
+       
+       // We set the good icon
+       presenceIcon(show);
+       
+       // We store our presence
+       if(!autoidle)
+               setDB('presence-show', 1, show);
+       
+       // We send the presence to our active MUC
+       $('.page-engine-chan[data-type=groupchat]').each(function() {
+               var tmp_nick = $(this).attr('data-nick');
+               
+               if(!tmp_nick)
+                       return;
+               
+               var room = unescape($(this).attr('data-xid'));
+               var nick = unescape(tmp_nick);
+               
+               // Must re-initialize?
+               if(RESUME)
+                       getMUC(room, nick);
+               
+               // Not disabled?
+               else if(!$(this).find('.message-area').attr('disabled'))
+                       sendPresence(room + '/' + nick, '', show, status, '', true);
+       });
+}
+
+// Changes the presence icon
+function presenceIcon(value) {
+       $('#my-infos .f-presence a.picker').attr('data-value', value);
+}
+
+// Sends a subscribe stanza
+function sendSubscribe(to, type) {
+       var status = '';
+       
+       // Subscribe request?
+       if(type == 'subscribe')
+               status = printf(_e("Hi, I am %s, I would like to add you as my friend."), getName());
+       
+       sendPresence(to, type, '', status);
+}
+
+// Accepts the subscription from another entity
+function acceptSubscribe(xid, name) {
+       // We update our chat
+       $('#' + hex_md5(xid) + ' .tools-add').hide();
+       
+       // We send a subsribed presence (to confirm)
+       sendSubscribe(xid, 'subscribed');
+       
+       // We send a subscription request (subscribe both sides)
+       sendSubscribe(xid, 'subscribe');
+       
+       // Specify the buddy name (if any)
+       if(name)
+               sendRoster(xid, '', name)
+}
+
+// Sends automatic away presence
+var AUTO_IDLE = false;
+
+function autoIdle() {
+       // Not connected?
+       if(!isConnected())
+               return;
+       
+       // Stop if an xa presence was set manually
+       var last_presence = getUserShow();
+       
+       if(!AUTO_IDLE && ((last_presence == 'away') || (last_presence == 'xa')))
+               return;
+       
+       var idle_presence;
+       var activity_limit;
+       
+       // Can we extend to auto extended away mode (20 minutes)?
+       if(AUTO_IDLE && (last_presence == 'away')) {
+               idle_presence = 'xa';
+               activity_limit = 1200;
+       }
+       
+       // We must set the user to auto-away (10 minutes)
+       else {
+               idle_presence = 'away';
+               activity_limit = 600;
+       }
+       
+       // The user is really inactive and has set another presence than extended away
+       if(((!AUTO_IDLE && (last_presence != 'away')) || (AUTO_IDLE && (last_presence == 'away'))) && (getLastActivity() >= activity_limit)) {
+               // Then tell we use an auto presence
+               AUTO_IDLE = true;
+               
+               // Get the old status message
+               var status = getDB('options', 'presence-status');
+               
+               if(!status)
+                       status = '';
+               
+               // Change the presence input
+               $('#my-infos .f-presence a.picker').attr('data-value', idle_presence);
+               $('#presence-status').val(status);
+               
+               // Then send the xa presence
+               presenceSend('', true);
+               
+               logThis('Auto-idle presence sent: ' + idle_presence, 3);
+       }
+}
+
+// Restores the old presence on a document bind
+function eventIdle() {
+       // If we were idle, restore our old presence
+       if(AUTO_IDLE) {
+               // Get the values
+               var show = getDB('presence-show', 1);
+               var status = getDB('options', 'presence-status');
+               
+               // Change the presence input
+               $('#my-infos .f-presence a.picker').attr('data-value', show);
+               $('#presence-status').val(status);
+               $('#presence-status').placeholder();
+               
+               // Then restore the old presence
+               presenceSend('', true);
+               
+               if(!show)
+                       show = 'available';
+               
+               logThis('Presence restored: ' + show, 3);
+       }
+       
+       // Apply some values
+       AUTO_IDLE = false;
+       LAST_ACTIVITY = getTimeStamp();
+}
+
+// Lives the auto idle functions
+function liveIdle() {
+       // Apply the autoIdle function every minute
+       AUTO_IDLE = false;
+       $('#my-infos .f-presence').everyTime('30s', autoIdle);
+       
+       // On body bind (click & key event)
+       $('body').live('mousedown', eventIdle)
+                .live('mousemove', eventIdle)
+                .live('keydown', eventIdle);
+}
+
+// Kills the auto idle functions
+function dieIdle() {
+       // Remove the event detector
+       $('body').die('mousedown', eventIdle)
+                .die('mousemove', eventIdle)
+                .die('keydown', eventIdle);
+}
+
+// Gets the user presence show
+function getUserShow() {
+       return $('#my-infos .f-presence a.picker').attr('data-value');
+}
+
+// Gets the user presence status
+function getUserStatus() {
+       return $('#presence-status').val();
+}
+
+// Plugin launcher
+function launchPresence() {
+       // Click event for user presence show
+       $('#my-infos .f-presence a.picker').click(function() {
+               // Disabled?
+               if($(this).hasClass('disabled'))
+                       return false;
+               
+               // Initialize some vars
+               var path = '#my-infos .f-presence div.bubble';
+               var show_id = ['xa', 'away', 'available'];
+               var show_lang = [_e("Not available"), _e("Away"), _e("Available")];
+               var show_val = getUserShow();
+               
+               // Yet displayed?
+               var can_append = true;
+               
+               if(exists(path))
+                       can_append = false;
+               
+               // Add this bubble!
+               showBubble(path);
+               
+               if(!can_append)
+                       return false;
+               
+               // Generate the HTML code
+               var html = '<div class="bubble removable">';
+               
+               for(i in show_id) {
+                       // Yet in use: no need to display it!
+                       if(show_id[i] == show_val)
+                               continue;
+                       
+                       html += '<a href="#" class="talk-images" data-value="' + show_id[i] + '" title="' + show_lang[i] + '"></a>';
+               }
+               
+               html += '</div>';
+               
+               // Append the HTML code
+               $('#my-infos .f-presence').append(html);
+               
+               // Click event
+               $(path + ' a').click(function() {
+                       // Update the presence show marker
+                       $('#my-infos .f-presence a.picker').attr('data-value', $(this).attr('data-value'));
+                       
+                       // Close the bubble
+                       closeBubbles();
+                       
+                       // Focus on the status input
+                       $(document).oneTime(10, function() {
+                               $('#presence-status').focus();
+                       });
+                       
+                       return false;
+               });
+               
+               return false;
+       });
+       
+       // Submit events for user presence status
+       $('#presence-status').placeholder()
+       
+       .keyup(function(e) {
+               if(e.keyCode == 13) {
+                       $(this).blur();
+                       
+                       return false;
+               }
+       })
+       
+       .blur(function() {
+               // Read the parameters
+               var show = getUserShow();
+               var status = getUserStatus();
+               
+               // Read the old parameters
+               var old_show = getDB('presence-show', 1);
+               var old_status = getDB('options', 'presence-status');
+               
+               // Must send the presence?
+               if((show != old_show) || (status != old_status)) {
+                       // Update the local stored status
+                       setDB('options', 'presence-status', status);
+                       
+                       // Update the server stored status
+                       if(status != old_status)
+                               storeOptions();
+                       
+                       // Send the presence
+                       presenceSend();
+               }
+       })
+       
+       // Input focus handler
+       .focus(function() {
+               closeBubbles();
+       });
+}
diff --git a/jappixmini/jappix/js/privacy.js b/jappixmini/jappix/js/privacy.js
new file mode 100644 (file)
index 0000000..01675f7
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+
+Jappix - An open social platform
+These are the privacy JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/06/11
+
+*/
+
+// Opens the privacy popup
+function openPrivacy() {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Privacy") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="privacy-head">' + 
+                       '<div class="list-left">' + 
+                               '<span>' + _e("Choose") + '</span>' + 
+                               '<select disabled=""></select>' + 
+                               '<a href="#" class="list-remove one-button talk-images" title="' + _e("Remove") + '"></a>' + 
+                       '</div>' + 
+                       
+                       '<div class="list-center"></div>' + 
+                       
+                       '<div class="list-right">' + 
+                               '<span>' + _e("Add") + '</span>' + 
+                               '<input type="text" placeholder="' + _e("List name") + '" />' + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div class="privacy-item">' + 
+                       '<span>' + _e("Item") + '</span>' + 
+                       '<select disabled=""></select>' + 
+                       '<a href="#" class="item-add one-button talk-images" title="' + _e("Add") + '"></a>' + 
+                       '<a href="#" class="item-remove one-button talk-images" title="' + _e("Remove") + '"></a>' + 
+                       '<a href="#" class="item-save one-button talk-images">' + _e("Save") + '</a>' + 
+                       
+                       '<div class="clear"></div>' + 
+               '</div>' + 
+               
+               '<div class="privacy-form">' + 
+                       '<div class="privacy-first">' + 
+                               '<label><input type="radio" name="action" value="allow" disabled="" />' + _e("Allow") + '</label>' + 
+                               '<label><input type="radio" name="action" value="deny" disabled="" />' + _e("Deny") + '</label>' + 
+                       '</div>' + 
+                       
+                       '<div class="privacy-second">' + 
+                               '<label><input type="radio" name="type" value="jid" disabled="" />' + _e("Address") + '</label>' + 
+                               '<input type="text" name="jid" disabled="" />' + 
+                               
+                               '<label><input type="radio" name="type" value="group" disabled="" />' + _e("Group") + '</label>' + 
+                               '<select name="group" disabled="">' + groupsToHtmlPrivacy() + '</select>' + 
+                               
+                               '<label><input type="radio" name="type" value="subscription" disabled="" />' + _e("Subscription") + '</label>' + 
+                               '<select name="subscription" disabled="">' + 
+                                       '<option value="none">' + _e("None") + '</option>' + 
+                                       '<option value="both">' + _e("Both") + '</option>' + 
+                                       '<option value="from">' + _e("From") + '</option>' + 
+                                       '<option value="to">' + _e("To") + '</option>' + 
+                               '</select>' + 
+                               
+                               '<label><input type="radio" name="type" value="everybody" disabled="" />' + _e("Everybody") + '</label>' + 
+                       '</div>' + 
+                       
+                       '<div class="privacy-third">' + 
+                               '<label><input type="checkbox" name="send-messages" disabled="" />' + _e("Send messages") + '</label>' + 
+                               '<label><input type="checkbox" name="send-queries" disabled="" />' + _e("Send queries") + '</label>' + 
+                               '<label><input type="checkbox" name="see-status" disabled="" />' + _e("See my status") + '</label>' + 
+                               '<label><input type="checkbox" name="send-status" disabled="" />' + _e("Send his/her status") + '</label>' + 
+                               '<label><input type="checkbox" name="everything" disabled="" />' + _e("Everything") + '</label>' + 
+                       '</div>' + 
+                       
+                       '<div class="clear"></div>' + 
+               '</div>' + 
+               
+               '<div class="privacy-active">' + 
+                       '<label>' + _e("Order") + '<input type="text" name="order" value="1" disabled="" /></label>' + 
+                       
+                       '<div class="privacy-active-elements">' + 
+                               '<label><input type="checkbox" name="active" disabled="" />' + _e("Active for this session") + '</label>' + 
+                               '<label><input type="checkbox" name="default" disabled="" />' + _e("Always active") + '</label>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('privacy', html);
+       
+       // Associate the events
+       launchPrivacy();
+       
+       // Display the available privacy lists
+       displayListsPrivacy();
+       
+       // Get the first list items
+       displayItemsPrivacy();
+       
+       return false;
+}
+
+// Quits the privacy popup
+function closePrivacy() {
+       // Destroy the popup
+       destroyPopup('privacy');
+       
+       return false;
+}
+
+// Sets the received state for privacy block list
+function receivedPrivacy() {
+       // Store marker
+       setDB('privacy-marker', 'available', 'true');
+       
+       // Show privacy elements
+       $('.privacy-hidable').show();
+}
+
+// Gets available privacy lists
+function listPrivacy() {
+       // Build query
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       iq.setQuery(NS_PRIVACY);
+       
+       con.send(iq, handleListPrivacy);
+       
+       logThis('Getting available privacy list(s)...');
+}
+
+// Handles available privacy lists
+function handleListPrivacy(iq) {
+       // Error?
+       if(iq.getType() == 'error')
+               return logThis('Privacy lists not supported!', 2);
+       
+       // Get IQ query content
+       var iqQuery = iq.getQuery();
+       
+       // Save the content
+       setDB('privacy-lists', 'available', xmlToString(iqQuery));
+       
+       // Any block list?
+       if($(iqQuery).find('list[name=block]').size()) {
+               // Not the default one?
+               if(!$(iqQuery).find('default[name=block]').size())
+                       changePrivacy('block', 'default');
+               else
+                       setDB('privacy-marker', 'default', 'block');
+               
+               // Not the active one?
+               if(!$(iqQuery).find('active[name=block]').size())
+                       changePrivacy('block', 'active');
+               else
+                       setDB('privacy-marker', 'active', 'block');
+               
+               // Get the block list rules
+               getPrivacy('block');
+       }
+       
+       // Apply the received marker here
+       else
+               receivedPrivacy();
+       
+       logThis('Got available privacy list(s).', 3);
+}
+
+// Gets privacy lists
+function getPrivacy(list) {
+       // Build query
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       // Privacy query
+       var iqQuery = iq.setQuery(NS_PRIVACY);
+       iqQuery.appendChild(iq.buildNode('list', {'xmlns': NS_PRIVACY, 'name': list}));
+       
+       con.send(iq, handleGetPrivacy);
+       
+       // Must show the wait item?
+       if(exists('#privacy'))
+               $('#privacy .wait').show();
+       
+       logThis('Getting privacy list(s): ' + list);
+}
+
+// Handles privacy lists
+function handleGetPrivacy(iq) {
+       // Apply a "received" marker
+       receivedPrivacy();
+       
+       // Store the data for each list
+       $(iq.getQuery()).find('list').each(function() {
+               // Read list name
+               var list_name = $(this).attr('name');
+               
+               // Store list content
+               setDB('privacy', list_name, xmlToString(this));
+               
+               // Is this a block list?
+               if(list_name == 'block') {
+                       // Reset buddies
+                       $('#buddy-list .buddy').removeClass('blocked');
+                       
+                       // XID types
+                       $(this).find('item[action=deny][type=jid]').each(function() {
+                               $('#buddy-list .buddy[data-xid=' + escape($(this).attr('value')) + ']').addClass('blocked');
+                       });
+                       
+                       // Group types
+                       $(this).find('item[action=deny][type=group]').each(function() {
+                               $('#buddy-list .group' + hex_md5($(this).attr('value')) + ' .buddy').addClass('blocked');
+                       });
+               }
+       });
+       
+       // Must display it to the popup?
+       if(exists('#privacy')) {
+               displayItemsPrivacy();
+               
+               $('#privacy .wait').hide();
+       }
+       
+       logThis('Got privacy list(s).', 3);
+}
+
+// Sets a privacy list
+function setPrivacy(list, types, values, actions, orders, presence_in, presence_out, msg, iq_p) {
+       // Build query
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // Privacy query
+       var iqQuery = iq.setQuery(NS_PRIVACY);
+       var iqList = iqQuery.appendChild(iq.buildNode('list', {'xmlns': NS_PRIVACY, 'name': list}));
+       
+       // Build the item elements
+       if(types && types.length) {
+               for(var i = 0; i < types.length; i++) {
+                       // Item element
+                       var iqItem = iqList.appendChild(iq.buildNode('item', {'xmlns': NS_PRIVACY}));
+                       
+                       // Item attributes
+                       if(types[i])
+                               iqItem.setAttribute('type', types[i]);
+                       if(values[i])
+                               iqItem.setAttribute('value', values[i]);
+                       if(actions[i])
+                               iqItem.setAttribute('action', actions[i]);
+                       if(orders[i])
+                               iqItem.setAttribute('order', orders[i]);
+                       
+                       // Child elements
+                       if(presence_in[i])
+                               iqItem.appendChild(iq.buildNode('presence-in', {'xmlns': NS_PRIVACY}));
+                       if(presence_out[i])
+                               iqItem.appendChild(iq.buildNode('presence-out', {'xmlns': NS_PRIVACY}));
+                       if(msg[i])
+                               iqItem.appendChild(iq.buildNode('message', {'xmlns': NS_PRIVACY}));
+                       if(iq_p[i])
+                               iqItem.appendChild(iq.buildNode('iq', {'xmlns': NS_PRIVACY}));
+               }
+       }
+       
+       con.send(iq);
+       
+       logThis('Sending privacy list: ' + list);
+}
+
+// Push a privacy list item to a list
+function pushPrivacy(list, type, value, action, order, presence_in, presence_out, msg, iq_p, hash, special_action) {
+       // Read the stored elements (to add them)
+       var stored = XMLFromString(getDB('privacy', list));
+       
+       // Read the first value
+       var first_val = value[0];
+       
+       // Must remove the given value?
+       if(special_action == 'remove') {
+               type = [];
+               value = [];
+               action = [];
+               order = [];
+               presence_in = [];
+               presence_out = [];
+               iq_p = [];
+       }
+       
+       // Serialize them to an array
+       $(stored).find('item').each(function() {
+               // Attributes
+               var c_type = $(this).attr('type');
+               var c_value = $(this).attr('value');
+               var c_action = $(this).attr('action');
+               var c_order = $(this).attr('order');
+               
+               // Generate hash
+               var c_hash = hex_md5(c_type + c_value + c_action + c_order);
+               
+               // Do not push it twice!
+               if(((c_hash != hash) && (special_action != 'roster')) || ((first_val != c_value) && (special_action == 'roster'))) {
+                       if(!c_type)
+                               c_type = '';
+                       if(!c_value)
+                               c_value = '';
+                       if(!c_action)
+                               c_action = '';
+                       if(!c_order)
+                               c_order = '';
+                       
+                       type.push(c_type);
+                       value.push(c_value);
+                       action.push(c_action);
+                       order.push(c_order);
+                       
+                       // Child elements
+                       if($(this).find('presence-in').size())
+                               presence_in.push(true);
+                       else
+                               presence_in.push(false);
+                       
+                       if($(this).find('presence-out').size())
+                               presence_out.push(true);
+                       else
+                               presence_out.push(false);
+                       
+                       if($(this).find('message').size())
+                               msg.push(true);
+                       else
+                               msg.push(false);
+                       
+                       if($(this).find('iq').size())
+                               iq_p.push(true);
+                       else
+                               iq_p.push(false);
+               }
+       });
+       
+       // Send it!
+       setPrivacy(list, type, value, action, order, presence_in, presence_out, msg, iq_p);
+}
+
+// Change a privacy list status
+function changePrivacy(list, status) {
+       // Yet sent?
+       if(getDB('privacy-marker', status) == list)
+               return;
+       
+       // Write a marker
+       setDB('privacy-marker', status, list);
+       
+       // Build query
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       // Privacy query
+       var iqQuery = iq.setQuery(NS_PRIVACY);
+       var iqStatus = iqQuery.appendChild(iq.buildNode(status, {'xmlns': NS_PRIVACY}));
+       
+       // Can add a "name" attribute?
+       if(list)
+               iqStatus.setAttribute('name', list);
+       
+       con.send(iq);
+       
+       logThis('Changing privacy list status: ' + list + ' to: ' + status);
+}
+
+// Checks the privacy status (action) of a value
+function statusPrivacy(list, value) {
+       return $(XMLFromString(getDB('privacy', list))).find('item[value=' + value + ']').attr('action');
+}
+
+// Converts the groups array into a <option /> string
+function groupsToHtmlPrivacy() {
+       var groups = getAllGroups();
+       var html = '';
+       
+       // Generate HTML
+       for(i in groups) {
+               html += '<option value="' + encodeQuotes(groups[i]) +'">' + groups[i].htmlEnc() + '</option>';
+       }
+       
+       return html;
+}
+
+// Displays the privacy lists
+function displayListsPrivacy() {
+       // Initialize
+       var code = '';
+       var select = $('#privacy .privacy-head .list-left select');
+       var data = XMLFromString(getDB('privacy-lists', 'available'));
+       
+       // Parse the XML data!
+       $(data).find('list').each(function() {
+               var list_name = $(this).attr('name');
+               
+               if(list_name)
+                       code += '<option value="' + encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>';
+       });
+       
+       // Apply HTML code
+       select.html(code);
+       
+       // Not empty?
+       if(code)
+               select.removeAttr('disabled');
+       else
+               select.attr('disabled', true);
+       
+       return true;
+}
+
+// Displays the privacy items for a list
+function displayItemsPrivacy() {
+       // Reset the form
+       clearFormPrivacy();
+       disableFormPrivacy();
+       
+       // Initialize
+       var code = '';
+       var select = $('#privacy .privacy-item select');
+       var list = $('#privacy .privacy-head .list-left select').val();
+       
+       // Reset the item select
+       select.html('');
+       
+       // No list?
+       if(!list)
+               return false;
+       
+       // Reset the list status
+       $('#privacy .privacy-active input[type=checkbox]').removeAttr('checked');
+       
+       // Display the list status
+       var status = ['active', 'default'];
+       
+       for(s in status) {
+               if(getDB('privacy-marker', status[s]) == list)
+                       $('#privacy .privacy-active input[name=' + status[s] + ']').attr('checked', true);
+       }
+       
+       // Try to read the stored items
+       var items = XMLFromString(getDB('privacy', list));
+       
+       // Must retrieve the data?
+       if(!items) {
+               select.attr('disabled', true);
+               
+               return getPrivacy(list);
+       }
+       
+       else
+               select.removeAttr('disabled');
+       
+       // Parse the XML data!
+       $(items).find('item').each(function() {
+               // Read attributes
+               var item_type = $(this).attr('type');
+               var item_value = $(this).attr('value');
+               var item_action = $(this).attr('action');
+               var item_order = $(this).attr('order');
+               
+               // Generate hash
+               var item_hash = hex_md5(item_type + item_value + item_action + item_order);
+               
+               // Read sub-elements
+               var item_presencein = $(this).find('presence-in').size();
+               var item_presenceout = $(this).find('presence-out').size();
+               var item_message = $(this).find('message').size();
+               var item_iq = $(this).find('iq').size();
+               
+               // Apply default values (if missing)
+               if(!item_type)
+                       item_type = '';
+               if(!item_value)
+                       item_value = '';
+               if(!item_action)
+                       item_action = 'allow';
+               if(!item_order)
+                       item_order = '1';
+               
+               // Apply sub-elements values
+               if(item_presencein)
+                       item_presencein = 'true';
+               else
+                       item_presencein = 'false';
+               
+               if(item_presenceout)
+                       item_presenceout = 'true';
+               else
+                       item_presenceout = 'false';
+               
+               if(item_message)
+                       item_message = 'true';
+               else
+                       item_message = 'false';
+               
+               if(item_iq)
+                       item_iq = 'true';
+               else
+                       item_iq = 'false';
+               
+               // Generate item description
+               var desc = '';
+               var desc_arr = [item_type, item_value, item_action, item_order];
+               
+               for(d in desc_arr) {
+                       // Nothing to display?
+                       if(!desc_arr[d])
+                               continue;
+                       
+                       if(desc)
+                               desc += ' - ';
+                       
+                       desc += desc_arr[d];
+               }
+               
+               // Add the select option
+               code += '<option data-type="' + encodeQuotes(item_type) + '" data-value="' + encodeQuotes(item_value) + '" data-action="' + encodeQuotes(item_action) + '" data-order="' + encodeQuotes(item_order) + '" data-presence_in="' + encodeQuotes(item_presencein) + '" data-presence_out="' + encodeQuotes(item_presenceout) + '" data-message="' + encodeQuotes(item_message) + '" data-iq="' + encodeQuotes(item_iq) + '" data-hash="' + encodeQuotes(item_hash) + '">' + 
+                               desc + 
+                       '</option>';
+       });
+       
+       // Append the code
+       select.append(code);
+       
+       // Display the first item form
+       var first_item = select.find('option:first');
+       displayFormPrivacy(
+                          first_item.attr('data-type'),
+                          first_item.attr('data-value'),
+                          first_item.attr('data-action'),
+                          first_item.attr('data-order'),
+                          first_item.attr('data-presence_in'),
+                          first_item.attr('data-presence_out'),
+                          first_item.attr('data-message'),
+                          first_item.attr('data-iq')
+                         );
+       
+       return true;
+}
+
+// Displays the privacy form for an item
+function displayFormPrivacy(type, value, action, order, presence_in, presence_out, message, iq) {
+       // Reset the form
+       clearFormPrivacy();
+       
+       // Apply the action
+       $('#privacy .privacy-first input[name=action][value=' + action + ']').attr('checked', true);
+       
+       // Apply the type & value
+       var privacy_second = '#privacy .privacy-second';
+       var privacy_type = privacy_second + ' input[name=type]';
+       var type_check, value_input;
+       
+       switch(type) {
+               case 'jid':
+                       type_check = privacy_type + '[value=jid]';
+                       value_input = privacy_second + ' input[type=text][name=jid]';
+                       
+                       break;
+               
+               case 'group':
+                       type_check = privacy_type + '[value=group]';
+                       value_input = privacy_second + ' select[name=group]';
+                       
+                       break;
+               
+               case 'subscription':
+                       type_check = privacy_type + '[value=subscription]';
+                       value_input = privacy_second + ' select[name=subscription]';
+                       
+                       break;
+               
+               default:
+                       type_check = privacy_type + '[value=everybody]';
+                       
+                       break;
+       }
+       
+       // Check the target
+       $(type_check).attr('checked', true);
+       
+       // Can apply a value?
+       if(value_input)
+               $(value_input).val(value);
+       
+       // Apply the things to do
+       var privacy_do = '#privacy .privacy-third input[type=checkbox]';
+       
+       if(presence_in == 'true')
+               $(privacy_do + '[name=send-status]').attr('checked', true);
+       if(presence_out == 'true')
+               $(privacy_do + '[name=see-status]').attr('checked', true);
+       if(message == 'true')
+               $(privacy_do + '[name=send-messages]').attr('checked', true);
+       if(iq == 'true')
+               $(privacy_do + '[name=send-queries]').attr('checked', true);
+       
+       if(!$(privacy_do).filter(':checked').size())
+               $(privacy_do + '[name=everything]').attr('checked', true);
+       
+       // Apply the order
+       $('#privacy .privacy-active input[name=order]').val(order);
+       
+       // Enable the forms
+       $('#privacy .privacy-form input, #privacy .privacy-form select, #privacy .privacy-active input').removeAttr('disabled');
+}
+
+// Clears the privacy list form
+function clearFormPrivacy() {
+       // Uncheck checkboxes & radio inputs
+       $('#privacy .privacy-form input[type=checkbox], #privacy .privacy-form input[type=radio]').removeAttr('checked');
+       
+       // Reset select
+       $('#privacy .privacy-form select option').removeAttr('selected');
+       $('#privacy .privacy-form select option:first').attr('selected', true);
+       
+       // Reset text input
+       $('#privacy .privacy-form input[type=text]').val('');
+       
+       // Reset order input
+       $('#privacy .privacy-active input[name=order]').val('1');
+}
+
+// Disables the privacy list form
+function disableFormPrivacy() {
+       $('#privacy .privacy-form input, #privacy .privacy-form select, #privacy .privacy-active input').attr('disabled', true);
+}
+
+// Enables the privacy list form
+function enableFormPrivacy(rank) {
+       $('#privacy .privacy-' + rank + ' input, #privacy .privacy-' + rank + ' select').removeAttr('disabled');
+}
+
+// Plugin launcher
+function launchPrivacy() {
+       // Click events
+       $('#privacy .bottom .finish').click(closePrivacy);
+       
+       // Placeholder events
+       $('#privacy input[placeholder]').placeholder();
+       
+       // Form events
+       $('#privacy .privacy-head a.list-remove').click(function() {
+               // Get list name
+               var list = $('#privacy .privacy-head .list-left select').val();
+               
+               // No value?
+               if(!list)
+                       return false;
+               
+               // Remove it from popup
+               $('#privacy .privacy-head .list-left select option[value=' + list + ']').remove();
+               
+               // Nothing remaining?
+               if(!exists('#privacy .privacy-head .list-left select option'))
+                       $('#privacy .privacy-head .list-left select option').attr('disabled', true);
+               
+               // Empty the item select
+               $('#privacy .privacy-item select').attr('disabled', true).html('');
+               
+               // Disable this list before removing it
+               var status = ['active', 'default'];
+               
+               for(s in status) {
+                       if(getDB('privacy-marker', status[s]) == list)
+                               changePrivacy('', status[s]);
+               }
+               
+               // Remove from server
+               setPrivacy(list);
+               
+               // Reset the form
+               clearFormPrivacy();
+               disableFormPrivacy();
+               
+               return false;
+       });
+       
+       $('#privacy .privacy-head .list-right input').keyup(function(e) {
+               // Not enter?
+               if(e.keyCode != 13)
+                       return;
+               
+               // Get list name
+               var list = $('#privacy .privacy-head .list-right input').val();
+               var select = '#privacy .privacy-head .list-left select';
+               var existed = true;
+               
+               // Create the new element
+               if(!exists(select + ' option[value=' + list + ']')) {
+                       // Marker
+                       existed = false;
+                       
+                       // Create a new option
+                       $(select).append('<option value="' + encodeQuotes(list) + '">' + list.htmlEnc() + '</option>');
+                       
+                       // Reset the item select
+                       $('#privacy .privacy-item select').attr('disabled', true).html('');
+               }
+               
+               // Change the select value & enable it
+               $(select).val(list).removeAttr('disabled');
+               
+               // Reset its value
+               $(this).val('');
+               
+               // Reset the form
+               clearFormPrivacy();
+               disableFormPrivacy();
+               
+               // Must reload the list items?
+               if(existed) {
+                       displayItemsPrivacy();
+                       $('#privacy .privacy-item select').removeAttr('disabled');
+               }
+       });
+       
+       $('#privacy .privacy-head .list-left select').change(displayItemsPrivacy);
+       
+       $('#privacy .privacy-item select').change(function() {
+               // Get the selected item
+               var item = $(this).find('option:selected');
+               
+               // Display the data!
+               displayFormPrivacy(
+                          item.attr('data-type'),
+                          item.attr('data-value'),
+                          item.attr('data-action'),
+                          item.attr('data-order'),
+                          item.attr('data-presence_in'),
+                          item.attr('data-presence_out'),
+                          item.attr('data-message'),
+                          item.attr('data-iq')
+                         );
+       });
+       
+       $('#privacy .privacy-item a.item-add').click(function() {
+               // Cannot add anything?
+               if(!exists('#privacy .privacy-head .list-left select option:selected'))
+                       return false;
+               
+               // Disable item select
+               $('#privacy .privacy-item select').attr('disabled', true);
+               
+               // Reset the form
+               clearFormPrivacy();
+               disableFormPrivacy();
+               
+               // Enable first form item
+               enableFormPrivacy('first');
+               enableFormPrivacy('active');
+               
+               return false;
+       });
+       
+       $('#privacy .privacy-item a.item-remove').click(function() {
+               // Cannot add anything?
+               if(!exists('#privacy .privacy-head .list-left select option:selected'))
+                       return false;
+               
+               // Get values
+               var list = $('#privacy .privacy-head .list-left select').val();
+               var selected = $('#privacy .privacy-item select option:selected');
+               var item = selected.attr('data-value');
+               var hash = selected.attr('data-hash');
+               
+               // Remove it from popup
+               $('#privacy .privacy-item select option:selected').remove();
+               
+               // No more items in this list?
+               if(!exists('#privacy .privacy-item select option')) {
+                       // Disable this select
+                       $('#privacy .privacy-item select').attr('disabled', true);
+                       
+                       // Remove the privacy list select item
+                       $('#privacy .privacy-head .list-left select option[value=' + list + ']').remove();
+                       
+                       // No more privacy lists?
+                       if(!exists('#privacy .privacy-head .list-left select option'))
+                               $('#privacy .privacy-head .list-left select').attr('disabled', true);
+                       
+                       // Disable this list before removing it
+                       var status = ['active', 'default'];
+                       
+                       for(s in status) {
+                               if(getDB('privacy-marker', status[s]) == list)
+                                       changePrivacy('', status[s]);
+                       }
+               }
+               
+               // Synchronize it with server
+               pushPrivacy(list, [], [item], [], [], [], [], [], [], hash, 'remove');
+               
+               // Reset the form
+               clearFormPrivacy();
+               disableFormPrivacy();
+               
+               return false;
+       });
+       
+       $('#privacy .privacy-item a.item-save').click(function() {
+               // Canot push item?
+               if(exists('#privacy .privacy-form input:disabled'))
+                       return false;
+               
+               // Get the hash
+               var item_hash = '';
+               
+               if(!$('#privacy .privacy-item select').is(':disabled'))
+                       item_hash = $('#privacy .privacy-item select option:selected').attr('data-hash');
+               
+               // Read the form
+               var privacy_second = '#privacy .privacy-second';
+               var item_list = $('#privacy .privacy-head .list-left select').val();
+               var item_action = $('#privacy .privacy-first input[name=action]').filter(':checked').val();
+               var item_type = $(privacy_second + ' input[name=type]').filter(':checked').val();
+               var item_order = $('#privacy .privacy-active input[name=order]').val();
+               var item_value = '';
+               
+               // Switch the type to get the value
+               switch(item_type) {
+                       case 'jid':
+                               item_value = $(privacy_second + ' input[type=text][name=jid]').val();
+                               
+                               break;
+                       
+                       case 'group':
+                               item_value = $(privacy_second + ' select[name=group]').val();
+                               
+                               break;
+                       
+                       case 'subscription':
+                               item_value = $(privacy_second + ' select[name=subscription]').val();
+                               
+                               break;
+                       
+                       default:
+                               item_type = '';
+                               
+                               break;
+               }
+               
+               // Get the selected things to do
+               var privacy_third_cb = '#privacy .privacy-third input[type=checkbox]';
+               var item_prin = false;
+               var item_prout = false;
+               var item_msg = false;
+               var item_iq = false;
+               
+               // Individual select?
+               if(!$(privacy_third_cb + '[name=everything]').filter(':checked').size()) {
+                       if($(privacy_third_cb + '[name=send-messages]').filter(':checked').size())
+                               item_msg = true;
+                       if($(privacy_third_cb + '[name=send-queries]').filter(':checked').size())
+                               item_iq = true;
+                       if($(privacy_third_cb + '[name=send-queries]').filter(':checked').size())
+                               item_iq = true;
+                       if($(privacy_third_cb + '[name=see-status]').filter(':checked').size())
+                               item_prout = true;
+                       if($(privacy_third_cb + '[name=send-status]').filter(':checked').size())
+                               item_prin = true;
+               }
+               
+               // Push item to the server!
+               pushPrivacy(
+                           item_list,
+                           [item_type],
+                           [item_value],
+                           [item_action],
+                           [item_order],
+                           [item_prin],
+                           [item_prout],
+                           [item_msg],
+                           [item_iq],
+                           item_hash
+                          );
+               
+               return false;
+       });
+       
+       $('#privacy .privacy-first input').change(function() {
+               enableFormPrivacy('second');
+       });
+       
+       $('#privacy .privacy-second input').change(function() {
+               enableFormPrivacy('third');
+       });
+       
+       $('#privacy .privacy-third input[type=checkbox]').change(function() {
+               // Target
+               var target = '#privacy .privacy-third input[type=checkbox]';
+               
+               // Must tick "everything" checkbox?
+               if(!$(target).filter(':checked').size())
+                       $(target + '[name=everything]').attr('checked', true);
+               
+               // Must untick the other checkboxes?
+               else if($(this).is('[name=everything]'))
+                       $(target + ':not([name=everything])').removeAttr('checked');
+               
+               // Must untick "everything" checkbox?
+               else
+                       $(target + '[name=everything]').removeAttr('checked');
+       });
+       
+       $('#privacy .privacy-active input[name=order]').keyup(function() {
+               // Get the value
+               var value = $(this).val();
+               
+               // No value?
+               if(!value)
+                       return;
+               
+               // Not a number?
+               if(isNaN(value))
+                       value = 1;
+               else
+                       value = parseInt(value);
+               
+               // Negative?            
+               if(value < 0)
+                       value = value * -1;
+               
+               // Apply the filtered value
+               $(this).val(value);
+       })
+       
+       .blur(function() {
+               // No value?
+               if(!$(this).val())
+                       $(this).val('1');
+       });
+       
+       $('#privacy .privacy-active .privacy-active-elements input').change(function() {
+               // Get the values
+               var list_name = $('#privacy .privacy-head .list-left select').val();
+               var state_name = $(this).attr('name');
+               
+               // Cannot continue?
+               if(!list_name || !state_name)
+                       return;
+               
+               // Change the current list status
+               if($(this).filter(':checked').size())
+                       changePrivacy(list_name, state_name);
+               else
+                       changePrivacy('', state_name);
+       });
+}
diff --git a/jappixmini/jappix/js/receipts.js b/jappixmini/jappix/js/receipts.js
new file mode 100644 (file)
index 0000000..1e6bf67
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+
+Jappix - An open social platform
+These are the receipts JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/12/10
+
+*/
+
+// Checks if we can send a receipt request
+function receiptRequest(hash) {
+       // Entity have support for receipt?
+       if($('#' + hash + ' .message-area').attr('data-receipts') == 'true')
+               return true;
+       
+       return false;
+}
+
+// Checks if there is a receipt request
+function hasReceipt(packet) {
+       // Any receipt request?
+       if(packet.getChild('request', NS_URN_RECEIPTS))
+               return true;
+       
+       return false;
+}
+
+// Checks if there is a received reply
+function hasReceived(packet) {
+       // Any received reply?
+       if(packet.getChild('received', NS_URN_RECEIPTS))
+               return true;
+       
+       return false;
+}
+
+// Sends a received notification
+function sendReceived(type, to, id) {
+       var aMsg = new JSJaCMessage();
+       aMsg.setTo(to);
+       aMsg.setID(id);
+       
+       // Any type?
+       if(type)
+               aMsg.setType(type);
+       
+       // Append the received node
+       aMsg.appendNode('received', {'xmlns': NS_URN_RECEIPTS, 'id': id});
+       
+       con.send(aMsg);
+       
+       logThis('Sent received to: ' + to);
+}
+
+// Tells the message has been received
+function messageReceived(hash, id) {
+       // Line selector
+       var path = $('#' + hash + ' .one-line[data-id=' + id + ']');
+       
+       // Add a received marker
+       path.attr('data-received', 'true')
+           .removeAttr('data-lost');
+       
+       // Group selector
+       var group = path.parent();
+       
+       // Remove the group marker
+       if(!group.find('.one-line[data-lost]').size()) {
+               group.find('b.name').removeClass('talk-images')
+                                   .removeAttr('title');
+       }
+       
+       return false;
+}
+
+// Checks if the message has been received
+function checkReceived(hash, id) {
+       // Fire a check 10 seconds later
+       $('#' + hash + ' .one-line[data-id=' + id + ']').oneTime('10s', function() {
+               // Not received?
+               if($(this).attr('data-received') != 'true') {
+                       // Add a "lost" marker
+                       $(this).attr('data-lost', 'true');
+                       
+                       // Add a warn on the buddy-name
+                       $(this).parent().find('b.name').addClass('talk-images')
+                                                      .attr('title', _e("Your friend seems not to have received your message(s)!"));
+               }
+       });
+}
diff --git a/jappixmini/jappix/js/roster.js b/jappixmini/jappix/js/roster.js
new file mode 100644 (file)
index 0000000..99389a7
--- /dev/null
@@ -0,0 +1,1122 @@
+/*
+
+Jappix - An open social platform
+These are the roster JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 19/05/11
+
+*/
+
+// Gets the roster items
+function getRoster() {
+       var iq = new JSJaCIQ();
+       
+       iq.setType('get');
+       iq.setQuery(NS_ROSTER);
+       
+       con.send(iq, handleRoster);
+}
+
+// Handles the roster items
+function handleRoster(iq) {
+       // Define some variables
+       var handleXML = iq.getQuery();
+       var current, xid, dName, subscription, group, xidHash, getNick, nick;
+       
+       // Parse the vcard xml
+       $(handleXML).find('item').each(function() {
+               parseRoster($(this), 'load');
+       });
+       
+       // Update our avatar (if changed), and send our presence
+       getAvatar(getXID(), 'force', 'true', 'forget');
+       
+       logThis('Roster received.');
+}
+
+// Parses the group XML and display the roster
+function parseRoster(current, mode) {
+       // Get the values
+       xid = current.attr('jid');
+       dName = current.attr('name');
+       subscription = current.attr('subscription');
+       xidHash = hex_md5(xid);
+       
+       // Create an array containing the groups
+       var groups = new Array();
+       
+       current.find('group').each(function() {
+               var group_text = $(this).text();
+               
+               if(group_text)
+                       groups.push(group_text);
+       });
+       
+       // No group?
+       if(!groups.length)
+               groups.push(_e("Unclassified"));
+       
+       // If no name is defined, we get the default nick of the buddy
+       if(!dName)
+               dName = getXIDNick(xid);
+       
+       displayRoster(xid, xidHash, dName, subscription, groups, mode);
+}
+
+// Updates the roster groups
+function updateGroups() {
+       $('#buddy-list .one-group').each(function() {
+               // Current values
+               var check = $(this).find('.buddy').size();
+               var hidden = $(this).find('.buddy:not(.hidden-buddy:hidden)').size();
+               
+               // Special case: the filtering tool
+               if(SEARCH_FILTERED)
+                       hidden = $(this).find('.buddy:visible').size();
+               
+               // If the group is empty
+               if(!check)
+                       $(this).remove();
+               
+               // If the group contains no online buddy (and is not just hidden)
+               if(!hidden && $(this).find('a.group').hasClass('minus'))
+                       $(this).hide();
+               else
+                       $(this).show();
+       });
+}
+
+// Displays a defined roster item
+function displayRoster(dXID, dXIDHash, dName, dSubscription, dGroup, dMode) {
+       // First remove the buddy
+       $('#buddy-list .' + dXIDHash).remove();
+       
+       // Define some things around the groups
+       var is_gateway = isGateway(dXID);
+       var gateway = '';
+       
+       if(is_gateway) {
+               gateway = ' gateway';
+               dGroup = new Array(_e("Gateways"));
+       }
+       
+       // Remove request (empty his social channel)
+       if(dSubscription == 'remove')
+               $('#channel .mixed .one-update.update_' + dXIDHash).remove();
+       
+       // Other request
+       else {
+               // Is this buddy blocked?
+               var privacy_class = '';
+               var privacy_state = statusPrivacy('block', dXID);
+               
+               if(privacy_state == 'deny')
+                       privacy_class = ' blocked';
+               
+               // For each group this buddy has
+               for(i in dGroup) {
+                       var cGroup = dGroup[i];
+                       
+                       if(cGroup) {
+                               // Process some vars
+                               var groupHash = 'group' + hex_md5(cGroup);
+                               var groupContent = '#buddy-list .' + groupHash;
+                               var groupBuddies = groupContent + ' .group-buddies';
+                               
+                               // Is this group blocked?
+                               if((statusPrivacy('block', cGroup) == 'deny') && (privacy_state != 'allow'))
+                                       privacy_class = ' blocked';
+                               
+                               // Group not yet displayed
+                               if(!exists(groupContent)) {
+                                       // Define some things
+                                       var groupCont = '#buddy-list .content';
+                                       var groupToggle = groupCont + ' .' + groupHash + ' a.group';
+                                       
+                                       // Create the HTML markup of the group
+                                       $(groupCont).prepend(
+                                               '<div class="' + groupHash + ' one-group" data-group="' + escape(cGroup) + '">' + 
+                                                       '<a href="#" class="group talk-images minus">' + cGroup.htmlEnc() + '</a>' + 
+                                                       '<div class="group-buddies"></div>' + 
+                                               '</div>'
+                                       );
+                                       
+                                       // Create the click event which will hide and show the content
+                                       $(groupToggle).click(function() {
+                                               var group = $(groupBuddies);
+                                               var group_toggle = $(groupContent + ' a.group');
+                                               
+                                               // We must hide the buddies
+                                               if(group_toggle.hasClass('minus')) {
+                                                       group.hide();
+                                                       group_toggle.removeClass('minus').addClass('plus');
+                                                       
+                                                       // Remove the group opened buddy-info
+                                                       closeBubbles();
+                                               }
+                                               
+                                               // We must show the buddies
+                                               else {
+                                                       group_toggle.removeClass('plus').addClass('minus');
+                                                       group.show();
+                                               }
+                                               
+                                               return false;
+                                       });
+                               }
+                               
+                               // Initialize the HTML code
+                               var name_code = '<p class="buddy-name">' + dName.htmlEnc() + '</p>';
+                               var presence_code = '<p class="buddy-presence talk-images unavailable">' + _e("Unavailable") + '</p>';
+                               
+                               var html = '<div class="hidden-buddy buddy ibubble ' + dXIDHash + gateway + privacy_class + '" data-xid="' + escape(dXID) + '">' + 
+                                               '<div class="buddy-click">';
+                               
+                               // Display avatar if not gateway
+                               if(!is_gateway)
+                                       html += '<div class="avatar-container">' + 
+                                                       '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                               '</div>';
+                               
+                               html += '<div class="name">';
+                               
+                               // Special gateway code
+                               if(is_gateway)
+                                       html += presence_code +
+                                               name_code;
+                               
+                               else
+                                       html += name_code + 
+                                               presence_code;
+                               
+                               html += '</div></div></div>';
+                               
+                               // Create the DOM element for this buddy
+                               $(groupBuddies).append(html);
+                               
+                               // Apply the hover event
+                               applyBuddyHover(dXID, dXIDHash, dName, dSubscription, dGroup, groupHash);
+                       }
+               }
+               
+               // Click event on this buddy
+               $('#buddy-list .' + dXIDHash + ' .buddy-click').click(function() {
+                       return checkChatCreate(dXID, 'chat');
+               });
+               
+               // We get the user presence if necessary
+               if(dMode == 'presence')
+                       presenceFunnel(dXID, dXIDHash);
+               
+               // If the buddy must be shown
+               if(BLIST_ALL)
+                       $('#buddy-list .' + dXIDHash).show();
+       }
+       
+       // We update our groups
+       if(!SEARCH_FILTERED)
+               updateGroups();
+       else
+               funnelFilterBuddySearch();
+}
+
+// Applies the buddy editing input events
+function applyBuddyInput(xid) {
+       // Initialize
+       var path = '#buddy-list .buddy[data-xid=' + escape(xid) + ']';
+       var rename = path + ' .bm-rename input';
+       var group = path + ' .bm-group input';
+       var manage_infos = path + ' .manage-infos';
+       var bm_choose = manage_infos + ' div.bm-choose';
+       
+       // Keyup events
+       $(rename).keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // Send the item
+                       sendRoster(xid, '', trim($(rename).val()), thisBuddyGroups(xid));
+                       
+                       // Remove the buddy editor
+                       closeBubbles();
+                       
+                       return false;
+               }
+       });
+       
+       $(group).keyup(function(e) {
+               if(e.keyCode == 13) {
+                       // Empty input?
+                       if(!trim($(this).val())) {
+                               // Send the item
+                               sendRoster(xid, '', trim($(rename).val()), thisBuddyGroups(xid));
+                               
+                               // Remove the buddy editor
+                               closeBubbles();
+                               
+                               return false;
+                       }
+                       
+                       // Get the values
+                       var this_value = trim($(this).val());
+                       var escaped_value = escape(this_value);
+                       
+                       // Check if the group yet exists
+                       var group_exists = false;
+                       
+                       $(bm_choose + ' label span').each(function() {
+                               if($(this).text() == this_value)
+                                       group_exists = true;
+                       });
+                       
+                       // Create a new checked checkbox
+                       if(!group_exists)
+                               $(bm_choose).prepend('<label><input type="checkbox" data-group="' + escaped_value + '" /><span>' + this_value.htmlEnc() + '</span></label>');
+                       
+                       // Check the checkbox
+                       $(bm_choose + ' input[data-group=' + escaped_value + ']').attr('checked', true);
+                       
+                       // Reset the value of this input
+                       $(this).val('');
+                       
+                       return false;
+               }
+       });
+       
+       // Click events
+       $(manage_infos + ' p.bm-authorize a.to').click(function() {
+               closeBubbles();
+               sendSubscribe(xid, 'subscribed');
+               
+               return false;
+       });
+       
+       $(manage_infos + ' p.bm-authorize a.from').click(function() {
+               closeBubbles();
+               sendSubscribe(xid, 'subscribe');
+               
+               return false;
+       });
+       
+       $(manage_infos + ' p.bm-authorize a.unblock').click(function() {
+               closeBubbles();
+               
+               // Update privacy settings
+               pushPrivacy('block', ['jid'], [xid], ['allow'], ['1'], [false], [true], [true], [true], '', 'roster');
+               $(path).removeClass('blocked');
+               
+               // Enable the "block" list
+               changePrivacy('block', 'active');
+               changePrivacy('block', 'default');
+               
+               // Send an available presence
+               sendPresence(xid, 'available', getUserShow(), getUserStatus());
+               
+               return false;
+       });
+       
+       $(manage_infos + ' p.bm-remove a.remove').click(function() {
+               closeBubbles();
+               sendRoster(xid, 'remove');
+               
+               return false;
+       });
+       
+       $(manage_infos + ' p.bm-remove a.prohibit').click(function() {
+               closeBubbles();
+               sendSubscribe(xid, 'unsubscribed');
+               
+               return false;
+       });
+       
+       $(manage_infos + ' p.bm-remove a.block').click(function() {
+               closeBubbles();
+               
+               // Update privacy settings
+               pushPrivacy('block', ['jid'], [xid], ['deny'], ['1'], [false], [true], [true], [true], '', 'roster');
+               $(path).addClass('blocked');
+               
+               // Enable the "block" list
+               changePrivacy('block', 'active');
+               changePrivacy('block', 'default');
+               
+               // Send an unavailable presence
+               sendPresence(xid, 'unavailable');
+               
+               // Remove the user presence
+               for(var i = 0; i < sessionStorage.length; i++) {
+                       // Get the pointer values
+                       var current = sessionStorage.key(i);
+                       
+                       // If the pointer is on a stored presence
+                       if((explodeThis('_', current, 0) == 'presence') && (bareXID(explodeThis('_', current, 1)) == xid))
+                               sessionStorage.removeItem(current);
+               }
+               
+               // Manage his new presence
+               presenceFunnel(xid, hex_md5(xid));
+               
+               return false;
+       });
+       
+       $(manage_infos + ' a.save').click(function() {
+               // Send the item
+               sendRoster(xid, '', trim($(rename).val()), thisBuddyGroups(xid));
+               
+               // Remove the buddy editor
+               closeBubbles();
+               
+               return false;
+       });
+}
+
+// Applies the buddy editing hover events
+function applyBuddyHover(xid, hash, nick, subscription, groups, group_hash) {
+       // Generate the values
+       var bPath = '#buddy-list .' + group_hash + ' .buddy[data-xid=' + escape(xid) + ']';
+       var iPath = bPath + ' .buddy-infos';
+       
+       // Apply the hover event
+       $(bPath).hover(function() {
+               // Another bubble exist
+               if(exists('#buddy-list .buddy-infos'))
+                       return false;
+               
+               $(bPath).oneTime(200, function() {
+                       // Another bubble exist
+                       if(exists('#buddy-list .buddy-infos'))
+                               return false;
+                       
+                       // Add this bubble!
+                       showBubble(iPath);
+                       
+                       // Create the buddy infos DOM element
+                       $(bPath).append(
+                               '<div class="buddy-infos bubble removable">' + 
+                                       '<div class="buddy-infos-subarrow talk-images"></div>' + 
+                                       '<div class="buddy-infos-subitem">' + 
+                                               '<div class="pep-infos">' + 
+                                                       '<p class="bi-status talk-images unavailable">' + _e("unknown") + '</p>' + 
+                                                       '<p class="bi-mood talk-images mood-four">' + _e("unknown") + '</p>' + 
+                                                       '<p class="bi-activity talk-images activity-exercising">' + _e("unknown") + '</p>' + 
+                                                       '<p class="bi-tune talk-images tune-note">' + _e("unknown") + '</p>' + 
+                                                       '<p class="bi-geoloc talk-images location-world">' + _e("unknown") + '</p>' + 
+                                                       '<p class="bi-view talk-images view-individual"><a href="#" class="profile">' + _e("Profile") + '</a> / <a href="#" class="channel">' + _e("Channel") + '</a> / <a href="#" class="commands">' + _e("Commands") + '</a></p>' + 
+                                                       '<p class="bi-edit talk-images edit-buddy"><a href="#">' + _e("Edit") + '</a></p>' + 
+                                               '</div>' + 
+                                       '</div>' + 
+                               '</div>'
+                       );
+                       
+                       // Sets the good position
+                       buddyInfosPosition(xid, group_hash);
+                       
+                       // Get the presence
+                       presenceFunnel(xid, hash);
+                       
+                       // Get the PEP infos
+                       displayAllPEP(xid);
+                       
+                       // Click events
+                       $(bPath + ' .bi-view a').click(function() {
+                               // Renitialize the buddy infos
+                               closeBubbles();
+                               
+                               // Profile
+                               if($(this).is('.profile'))
+                                       openUserInfos(xid);
+                               
+                               // Channel
+                               else if($(this).is('.channel'))
+                                       fromInfosMicroblog(xid, hash);
+                               
+                               // Command
+                               else if($(this).is('.commands'))
+                                       retrieveAdHoc(xid);
+                               
+                               return false;
+                       });
+                       
+                       $(bPath + ' .bi-edit a').click(function() {
+                               buddyEdit(xid, nick, subscription, groups);
+                               
+                               return false;
+                       });
+               });
+       }, function() {
+               if(!exists(iPath + ' .manage-infos'))
+                       closeBubbles();
+               
+               $(bPath).stopTime();
+       });
+}
+
+// Sets the good buddy-infos position
+function buddyInfosPosition(xid, group_hash) {
+       // Paths
+       var group = '#buddy-list .' + group_hash;
+       var buddy = group + ' .buddy[data-xid=' + escape(xid) + ']';
+       var buddy_infos = buddy + ' .buddy-infos';
+       
+       // Get the offset to define
+       var offset = 3;
+       
+       if(isGateway(xid))
+               offset = -8;
+       
+       // Process the position
+       var top = $(buddy).position().top + offset;
+       var left = $(buddy).width() - 10;
+       
+       // Apply the top position
+       $(buddy_infos).css('top', top)
+                     .css('left', left);
+}
+
+// Generates an array of the current groups of a buddy
+function thisBuddyGroups(xid) {
+       var path = '#buddy-list .buddy[data-xid=' + escape(xid) + '] ';
+       var array = new Array();
+       
+       // Each checked checkboxes
+       $(path + 'div.bm-choose input[type=checkbox]').filter(':checked').each(function() {
+               array.push(unescape($(this).attr('data-group')));
+       });
+       
+       // Entered input value (and not yet in the array)
+       var value = trim($(path + 'p.bm-group input').val());
+       
+       if(value && !existArrayValue(array, value))
+               array.push(value);
+       
+       return array;
+}
+
+// Adds a given contact to our roster
+function addThisContact(xid, name) {
+       logThis('Add this contact: ' + xid + ', as ' + name, 3);
+       
+       // Cut the resource of this XID
+       xid = bareXID(xid);
+       
+       // If the form is complete
+       if(xid) {
+               // We send the subscription
+               sendSubscribe(xid, 'subscribe');
+               sendRoster(xid, '', name);
+               
+               // We hide the bubble
+               closeBubbles();
+       }
+}
+
+// Gets an array of all the groups in the roster
+function getAllGroups() {
+       var groups = new Array();
+       
+       $('#buddy-list .one-group').each(function() {
+               var current = unescape($(this).attr('data-group'));
+               
+               if((current != _e("Unclassified")) && (current != _e("Gateways")))
+                       groups.push(current);
+       });
+       
+       return groups.sort();
+}
+
+// Edits buddy informations
+function buddyEdit(xid, nick, subscription, groups) {
+       logThis('Buddy edit: ' + xid, 3);
+       
+       // Initialize
+       var path = '#buddy-list .buddy[data-xid=' + escape(xid) + '] .';
+       var html = '<div class="manage-infos">';
+       
+       // Get the privacy state
+       var privacy_state = statusPrivacy('block', xid);
+       var privacy_active = getDB('privacy-marker', 'available');
+       
+       // Get the group privacy state
+       for(g in groups) {
+               if((statusPrivacy('block', groups[g]) == 'deny') && (privacy_state != 'allow'))
+                       privacy_state = 'deny';
+       }
+       
+       // The subscription with this buddy is not full
+       if((subscription != 'both') || ((privacy_state == 'deny') && privacy_active)) {
+               var authorize_links = '';
+               html += '<p class="bm-authorize talk-images">';
+               
+               // Link to allow to see our status
+               if((subscription == 'to') || (subscription == 'none'))
+                       authorize_links += '<a href="#" class="to">' + _e("Authorize") + '</a>';
+               
+               // Link to ask to see his/her status
+               if((subscription == 'from') || (subscription == 'none')) {
+                       if(authorize_links)
+                               authorize_links += ' / ';
+                       
+                       authorize_links += '<a href="#" class="from">' + _e("Ask for authorization") + '</a>';
+               }
+               
+               // Link to unblock this buddy
+               if((privacy_state == 'deny') && privacy_active) {
+                       if(authorize_links)
+                               authorize_links += ' / ';
+                       
+                       html += '<a href="#" class="unblock">' + _e("Unblock") + '</a>';
+               }
+               
+               html += authorize_links + '</p>';
+       }
+       
+       // Complete the HTML code
+       var remove_links = '';
+       html += '<p class="bm-remove talk-images">';
+       remove_links = '<a href="#" class="remove">' + _e("Remove") + '</a>';
+       
+       // This buddy is allowed to see our presence, we can show a "prohibit" link
+       if((subscription == 'both') || (subscription == 'from'))
+               remove_links += ' / <a href="#" class="prohibit">' + _e("Prohibit") + '</a>';
+       
+       // Complete the HTML code
+       if((privacy_state != 'deny') && privacy_active) {
+               if(remove_links)
+                       remove_links += ' / ';
+               
+               remove_links += '<a href="#" class="block">' + _e("Block") + '</a>';
+       }
+       
+       // Complete the HTML code
+       html += remove_links + 
+               '</p>' + 
+               '<p class="bm-rename talk-images"><label>' + _e("Rename") + '</label> <input type="text" value="' + encodeQuotes(nick) + '" /></p>';
+       
+       // Only show group tool if not a gateway
+       if(!isGateway(xid))
+               html += '<p class="bm-group talk-images"><label>' + _e("Groups") + '</label> <input type="text" /></p>' + 
+                       '<div class="bm-choose">' + 
+                               '<div></div>' + 
+                       '</div>';
+       
+       // Close the DOM element
+       html += '<a href="#" class="save">' + _e("Save") + '</a>' + 
+               '</div>';
+       
+       // We update the DOM elements
+       $(path + 'pep-infos').replaceWith(html);
+       
+       // Gets all the existing groups
+       var all_groups = getAllGroups();
+       var all_groups_dom = '';
+       
+       for(a in all_groups) {
+               // Current group
+               var all_groups_current = all_groups[a];
+               
+               // Is the current group checked?
+               var checked = '';
+               
+               if(existArrayValue(groups, all_groups_current))
+                       checked = ' checked="true"';
+               
+               // Add the current group HTML
+               all_groups_dom += '<label><input type="checkbox" data-group="' + escape(all_groups_current) + '"' + checked + ' /><span>' + all_groups_current.htmlEnc() + '</span></label>';
+       }
+       
+       // Prepend this in the DOM
+       var bm_choose = path + 'manage-infos div.bm-choose';
+       
+       $(bm_choose).prepend(all_groups_dom);
+       
+       // Apply the editing input events
+       applyBuddyInput(xid);
+}
+
+// Updates the roster items
+function sendRoster(xid, subscription, name, group) {
+       // We send the new buddy name
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var iqQuery = iq.setQuery(NS_ROSTER);
+       var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid}));
+       
+       // Any subscription?
+       if(subscription)
+               item.setAttribute('subscription', subscription);
+       
+       // Any name?
+       if(name)
+               item.setAttribute('name', name);
+       
+       // Any group?
+       if(group && group.length) {
+               for(i in group)
+                       item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, group[i]));
+       }
+       
+       con.send(iq);
+       
+       logThis('Roster item sent: ' + xid, 3);
+}
+
+// Adapts the roster height, depending of the window size
+function adaptRoster() {
+       // Process the new height
+       var new_height = $('#left-content').height() - $('#my-infos').height() - 97;
+       
+       // New height too small
+       if(new_height < 211)
+               new_height = 211;
+       
+       // Apply the new height
+       $('#buddy-list .content').css('height', new_height);
+}
+
+// Gets all the buddies in our roster
+function getAllBuddies() {
+       var buddies = new Array();
+       
+       $('#buddy-list .buddy').each(function() {
+               var xid = unescape($(this).attr('data-xid'));
+               
+               if(xid)
+                       buddies.push(xid);
+       });
+       
+       return buddies;
+}
+
+// Gets the user gateways
+function getGateways() {
+       // New array
+       var gateways = new Array();
+       var buddies = getAllBuddies();
+       
+       // Get the gateways
+       for(c in buddies) {
+               if(isGateway(buddies[c]))
+                       gateways.push(buddies[c]);
+       }
+       
+       return gateways;
+}
+
+// Define a global var for buddy list all buddies displayed
+var BLIST_ALL = false;
+
+// Plugin launcher
+function launchRoster() {
+       // Filtering tool
+       var iFilter = $('#buddy-list .filter input');
+       var aFilter = $('#buddy-list .filter a');
+       
+       iFilter.placeholder()
+       
+       .blur(function() {
+               // Nothing is entered, put the placeholder instead
+               if(!trim($(this).val()))
+                       aFilter.hide();
+               else
+                       aFilter.show();
+       })
+       
+       .keyup(function(e) {
+               funnelFilterBuddySearch(e.keyCode);
+       });
+       
+       aFilter.click(function() {
+               // Reset the input
+               $(this).hide();
+               iFilter.val('');
+               iFilter.placeholder();
+               
+               // Security: show all the groups, empty or not
+               $('#buddy-list .one-group').show();
+               
+               // Reset the filtering tool
+               resetFilterBuddySearch();
+               
+               return false;
+       });
+       
+       // When the user click on the add button, show the contact adding tool
+       $('#buddy-list .foot .add').click(function() {
+               // Yet displayed?
+               if(exists('#buddy-conf-add'))
+                       return closeBubbles();
+               
+               // Add the bubble
+               showBubble('#buddy-conf-add');
+               
+               // Append the content
+               $('#buddy-list .buddy-list-add').append(
+                       '<div id="buddy-conf-add" class="buddy-conf-item bubble removable">' + 
+                               '<div class="buddy-conf-subarrow talk-images"></div>' + 
+                               
+                               '<div class="buddy-conf-subitem">' + 
+                                       '<p class="buddy-conf-p">' + _e("Add a friend") +  '</p>' + 
+                                       
+                                       '<label><span>' + _e("Address") +  '</span><input type="text" class="buddy-conf-input add-contact-jid" required="" /></label>' + 
+                                       '<label><span>' + _e("Name") +  '</span><input type="text" class="buddy-conf-input add-contact-name" /></label>' +  
+                                       '<label>' + 
+                                               '<span>' + _e("Gateway") +  '</span>' + 
+                                               '<select class="buddy-conf-select add-contact-gateway">' + 
+                                                       '<option value="none" selected="">' + _e("None") +  '</option>' + 
+                                               '</select>' + 
+                                       '</label>' +  
+                                       '<span class="add-contact-name-get">' + _e("Getting the name...") + '</span>' + 
+                                       
+                                       '<p class="buddy-conf-text">' + 
+                                               '<a href="#" class="buddy-conf-add-search">' + _e("Search a friend") +  '</a>' + 
+                                       '</p>' + 
+                               '</div>' + 
+                       '</div>'
+               );
+               
+               // Add the gateways
+               var gateways = getGateways();
+               
+               // Any gateway?
+               if(gateways.length) {
+                       // Append the gateways
+                       for(i in gateways)
+                               $('.add-contact-gateway').append('<option value="' + escape(gateways[i]) + '">' + gateways[i].htmlEnc() +  '</option>');
+                       
+                       // Show the gateway selector
+                       $('.add-contact-gateway').parent().show();
+               }
+               
+               // No gateway?
+               else
+                       $('.add-contact-gateway').parent().hide();
+               
+               // Blur event on the add contact input
+               $('.add-contact-jid').blur(function() {
+                       // Read the value
+                       var value = trim($(this).val());
+                       
+                       // Try to catch the buddy name
+                       if(value && !trim($('.add-contact-name').val()) && ($('.add-contact-gateway').val() == 'none')) {
+                               // User XID
+                               var xid = generateXID(value, 'chat');
+                               
+                               // Notice for the user
+                               $('.add-contact-name-get').attr('data-for', escape(xid)).show();
+                               
+                               // Request the user vCard
+                               getAddUserName(xid);
+                       }
+               });
+               
+               // When a key is pressed...
+               $('#buddy-conf-add input, #buddy-conf-add select').keyup(function(e) {
+                       // Enter : continue
+                       if(e.keyCode == 13) {
+                               // Get the values
+                               var xid = trim($('.add-contact-jid').val());
+                               var name = trim($('.add-contact-name').val());
+                               var gateway = unescape($('.add-contact-gateway').val());
+                               
+                               // Generate the XID to add
+                               if((gateway != 'none') && xid)
+                                       xid = xid.replace(/@/g, '%') + '@' + gateway;
+                               else
+                                       xid = generateXID(xid, 'chat');
+                               
+                               // Submit the form
+                               if(xid && (xid != getXID()))
+                                       addThisContact(xid, name);
+                               else
+                                       $(document).oneTime(10, function() {
+                                               $('.add-contact-jid').addClass('please-complete').focus();
+                                       });
+                               
+                               return false;
+                       }
+                       
+                       // Escape : quit
+                       if(e.keyCode == 27)
+                               closeBubbles();
+               });
+               
+               // Click event on search link
+               $('.buddy-conf-add-search').click(function() {
+                       closeBubbles();
+                       return openDirectory();
+               });
+               
+               // Focus on the input
+               $(document).oneTime(10, function() {
+                       $('.add-contact-jid').focus();
+               });
+               
+               return false;
+       });
+       
+       // When the user click on the join button, show the chat joining tool
+       $('#buddy-list .foot .join').click(function() {
+               // Yet displayed?
+               if(exists('#buddy-conf-join'))
+                       return closeBubbles();
+               
+               // Add the bubble
+               showBubble('#buddy-conf-join');
+               
+               // Append the content
+               $('#buddy-list .buddy-list-join').append(
+                       '<div id="buddy-conf-join" class="buddy-conf-item bubble removable">' + 
+                               '<div class="buddy-conf-subarrow talk-images"></div>' + 
+                               
+                               '<div class="buddy-conf-subitem search">' + 
+                                       '<p class="buddy-conf-p" style="margin-bottom: 0;">' + _e("Join a chat") +  '</p>' + 
+                                       
+                                       '<input type="text" class="buddy-conf-input join-jid" required="" />' + 
+                                       '<select class="buddy-conf-select buddy-conf-join-select join-type">' + 
+                                               '<option value="chat" selected="">' + _e("Chat") +  '</option>' + 
+                                               '<option value="groupchat">' + _e("Groupchat") +  '</option>' + 
+                                       '</select>' + 
+                               '</div>' + 
+                       '</div>'
+               );
+               
+               // Input vars
+               var destination = '#buddy-conf-join .search';
+               var dHovered = destination + ' ul li.hovered:first';
+               
+               // When a key is pressed...
+               $('#buddy-conf-join input, #buddy-conf-join select').keyup(function(e) {
+                       // Enter: continue
+                       if(e.keyCode == 13) {
+                               // Select something from the search
+                               if(exists(dHovered))
+                                       addBuddySearch(destination, $(dHovered).attr('data-xid'));
+                               
+                               // Join something
+                               else {
+                                       var xid = trim($('.join-jid').val());
+                                       var type = $('.buddy-conf-join-select').val();
+                                       
+                                       if(xid && type) {
+                                               // Generate a correct XID
+                                               xid = generateXID(xid, type);
+                                               
+                                               // Not me
+                                               if(xid != getXID()) {
+                                                       // Update some things
+                                                       $('.join-jid').removeClass('please-complete');
+                                                       closeBubbles();
+                                                       
+                                                       // Create a new chat
+                                                       checkChatCreate(xid, type);
+                                               }
+                                               
+                                               else
+                                                       $('.join-jid').addClass('please-complete');
+                                       }
+                                       
+                                       else
+                                               $('.join-jid').addClass('please-complete');
+                               }
+                               
+                               return false;
+                       }
+                       
+                       // Escape: quit
+                       else if(e.keyCode == 27)
+                               closeBubbles();
+                       
+                       // Buddy search?
+                       else if($('.buddy-conf-join-select').val() == 'chat') {
+                               // New buddy search
+                               if((e.keyCode != 40) && (e.keyCode != 38))
+                                       createBuddySearch(destination);
+                               
+                               // Navigating with keyboard in the results
+                               arrowsBuddySearch(e, destination);
+                       }
+               });
+               
+               // Buddy search lost focus
+               $('#buddy-conf-join input').blur(function() {
+                       if(!$(destination + ' ul').attr('mouse-hover'))
+                               resetBuddySearch(destination);
+               });
+               
+               // Re-focus on the text input
+               $('#buddy-conf-join select').change(function() {
+                       $(document).oneTime(10, function() {
+                               $('#buddy-conf-join input').focus();
+                       });
+               });
+               
+               // We focus on the input
+               $(document).oneTime(10, function() {
+                       $('#buddy-conf-join .join-jid').focus();
+               });
+               
+               return false;
+       });
+       
+       // When the user click on the groupchat button, show the groupchat menu
+       $('#buddy-list .foot .groupchat').click(function() {
+               // Yet displayed?
+               if(exists('#buddy-conf-groupchat'))
+                       return closeBubbles();
+               
+               // Add the bubble
+               showBubble('#buddy-conf-groupchat');
+               
+               // Append the content
+               $('#buddy-list .buddy-list-groupchat').append(
+                       '<div id="buddy-conf-groupchat" class="buddy-conf-item bubble removable">' + 
+                               '<div class="buddy-conf-subarrow talk-images"></div>' + 
+                               
+                               '<div class="buddy-conf-subitem">' + 
+                                       '<p class="buddy-conf-p">' + _e("Your groupchats") +  '</p>' + 
+                                       
+                                       '<select name="groupchat-join" class="buddy-conf-select buddy-conf-groupchat-select"></select>' + 
+                                       
+                                       '<p class="buddy-conf-text">' + 
+                                               '- <a href="#" class="buddy-conf-groupchat-edit">' + _e("Manage your favorite groupchats") +  '</a>' + 
+                                       '</p>' + 
+                               '</div>' + 
+                       '</div>'
+               );
+               
+               // When the user wants to edit his groupchat favorites
+               $('.buddy-conf-groupchat-edit').click(function() {
+                       openFavorites();
+                       closeBubbles();
+                       
+                       return false;
+               });
+               
+               // Change event
+               $('.buddy-conf-groupchat-select').change(function() {
+                       var groupchat = trim($(this).val());
+                       
+                       if(groupchat != 'none') {
+                               // We hide the bubble
+                               closeBubbles();
+                               
+                               // Create the chat
+                               checkChatCreate(groupchat, 'groupchat');
+                               
+                               // We reset the select value
+                               $(this).val('none');
+                       }
+               });
+               
+               // Load the favorites
+               loadFavorites();
+               
+               return false;
+       });
+       
+       // When the user click on the more button, show the more menu
+       $('#buddy-list .foot .more').click(function() {
+               // Yet displayed?
+               if(exists('#buddy-conf-more'))
+                       return closeBubbles();
+               
+               // Add the bubble
+               showBubble('#buddy-conf-more');
+               
+               // Append the content
+               $('#buddy-list .buddy-list-more').append(
+                       '<div id="buddy-conf-more" class="buddy-conf-item bubble removable">' + 
+                               '<div class="buddy-conf-subarrow talk-images"></div>' + 
+                               
+                               '<div class="buddy-conf-subitem">' + 
+                                       '<p class="buddy-conf-p">' + _e("More stuff") +  '</p>' + 
+                                       
+                                       '<p class="buddy-conf-text">' + 
+                                               '- <a href="#" class="buddy-conf-more-display-unavailable">' + _e("Show all friends") +  '</a>' + 
+                                               '<a href="#" class="buddy-conf-more-display-available">' + _e("Only show connected friends") +  '</a>' + 
+                                       '</p>' + 
+                                       
+                                       '<p class="buddy-conf-text archives-hidable">' + 
+                                               '- <a href="#" class="buddy-conf-more-archives">' + _e("Message archives") +  '</a>' + 
+                                       '</p>' + 
+                                       
+                                       '<p class="buddy-conf-text privacy-hidable">' + 
+                                               '- <a href="#" class="buddy-conf-more-privacy">' + _e("Privacy") +  '</a>' + 
+                                       '</p>' + 
+                                       
+                                       '<p class="buddy-conf-text">' + 
+                                               '- <a href="#" class="buddy-conf-more-service-disco">' + _e("Service discovery") +  '</a>' + 
+                                       '</p>' + 
+                                       
+                                       '<p class="buddy-conf-text commands-hidable"">' + 
+                                               '- <a href="#" class="buddy-conf-more-commands">' + _e("Commands") +  '</a>' + 
+                                       '</p>' + 
+                               '</div>' + 
+                       '</div>'
+               );
+               
+               // Close bubble when link clicked
+               $('#buddy-conf-more a').click(function() {
+                       closeBubbles();
+               });
+               
+               // When the user wants to display all his buddies
+               $('.buddy-conf-more-display-unavailable').click(function() {
+                       showAllBuddies('roster');
+                       
+                       return false;
+               });
+               
+               // When the user wants to display only online buddies
+               $('.buddy-conf-more-display-available').click(function() {
+                       showOnlineBuddies('roster');
+                       
+                       return false;
+               });
+               
+               // When the user click on the archives link
+               $('.buddy-conf-more-archives').click(openArchives);
+               
+               // When the user click on the privacy link
+               $('.buddy-conf-more-privacy').click(openPrivacy);
+               
+               // When the user click on the service discovery link
+               $('.buddy-conf-more-service-disco').click(openDiscovery);
+               
+               // When the user click on the command link
+               $('.buddy-conf-more-commands').click(function() {
+                       serverAdHoc(con.domain);
+                       
+                       return false;
+               });
+               
+               // Manage the displayed links
+               if(BLIST_ALL) {
+                       $('.buddy-conf-more-display-unavailable').hide();
+                       $('.buddy-conf-more-display-available').show();
+               }
+               
+               if(enabledArchives() || enabledArchives('auto') || enabledArchives('manual') || enabledArchives('manage'))
+                       $('.buddy-conf-more-archives').parent().show();
+               
+               if(enabledCommands())
+                       $('.buddy-conf-more-commands').parent().show();
+               
+               if(getDB('privacy-marker', 'available'))
+                       $('.buddy-conf-more-privacy').parent().show();
+               
+               return false;
+       });
+       
+       // When the user scrolls the buddy list
+       $('#buddy-list .content').scroll(function() {
+               // Close the opened buddy infos bubble
+               closeBubbles();
+       });
+}
+
+// Window resize event handler
+$(window).resize(adaptRoster);
diff --git a/jappixmini/jappix/js/rosterx.js b/jappixmini/jappix/js/rosterx.js
new file mode 100644 (file)
index 0000000..30f0854
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+
+Jappix - An open social platform
+These are the Roster Item Exchange JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 23/06/11
+
+*/
+
+// Opens the welcome tools
+function openRosterX(data) {
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Suggested friends") + '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="rosterx-head">' + 
+                       '<a href="#" class="uncheck">' + _e("Uncheck all") + '</a>' + 
+                       '<a href="#" class="check">' + _e("Check all") + '</a>' + 
+               '</div>' + 
+               
+               '<div class="results"></div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<a href="#" class="finish save">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('rosterx', html);
+       
+       // Associate the events
+       launchRosterX();
+       
+       // Parse the data
+       parseRosterX(data);
+       
+       logThis('Roster Item Exchange popup opened.');
+}
+
+// Closes the welcome tools
+function closeRosterX() {
+       // Destroy the popup
+       destroyPopup('rosterx');
+       
+       return false;
+}
+
+// Parses a rosterx query
+function parseRosterX(data) {
+       // Main selector
+       var x = $(data).find('x[xmlns=' + NS_ROSTERX + ']:first');
+       
+       // Parse data
+       x.find('item').each(function() {
+               // Generate group XML
+               var group = '';
+               
+               $(this).find('group').each(function() {
+                       group += '<group>' + $(this).text().htmlEnc() + '</group>';
+               });
+               
+               if(group)
+                       group = '<groups>' + group + '</groups>';
+               
+               // Display it!
+               displayRosterX($(this).attr('jid'), $(this).attr('name'), group, $(this).attr('action'));
+       });
+       
+       // Click to check/uncheck
+       $('#rosterx .oneresult').click(function(evt) {
+               // No need to apply when click on input
+               if($(evt.target).is('input[type=checkbox]'))
+                       return;
+               
+               // Input selector
+               var checkbox = $(this).find('input[type=checkbox]');
+               
+               // Check or uncheck?
+               if(checkbox.filter(':checked').size())
+                       checkbox.removeAttr('checked');
+               else
+                       checkbox.attr('checked', true);
+       });
+}
+
+// Displays a rosterx item
+function displayRosterX(xid, nick, group, action) {
+       // End if no XID
+       if(!xid)
+               return false;
+       
+       // Set up a default action if no one
+       if(!action || (action != 'modify') || (action != 'delete'))
+               action = 'add';
+       
+       // Override "undefined" for nickname
+       if(!nick)
+               nick = '';
+       
+       // Display it
+       $('#rosterx .results').append(
+               '<div class="oneresult">' + 
+                       '<input type="checkbox" checked="" data-name="' + encodeQuotes(nick) + '" data-xid="' + encodeQuotes(xid) + '" data-action="' + encodeQuotes(action) + '" data-group="' + encodeQuotes(group) + '" />' + 
+                       '<span class="name">' + nick.htmlEnc() + '</span>' + 
+                       '<span class="xid">' + xid.htmlEnc() + '</span>' + 
+                       '<span class="action ' + action + ' talk-images"></span>' + 
+               '</div>'
+       );
+}
+
+// Saves the rosterx settings
+function saveRosterX() {
+       // Send the requests
+       $('#rosterx .results input[type=checkbox]').filter(':checked').each(function() {
+               // Read the attributes
+               var nick = $(this).attr('data-name');
+               var xid = $(this).attr('data-xid');
+               var action = $(this).attr('data-action');
+               var group = $(this).attr('data-group');
+               
+               // Parse groups XML
+               if(group) {
+                       var group_arr = []
+                       
+                       $(group).find('group').each(function() {
+                               group_arr.push($(this).text().revertHtmlEnc());
+                       });
+               }
+               
+               // Process the asked action
+               var roster_item = $('#buddy-list .' + hex_md5(xid));
+               
+               switch(action) {
+                       // Buddy add
+                       case 'add':
+                               if(!exists(roster_item)) {
+                                       sendSubscribe(xid, 'subscribe');
+                                       sendRoster(xid, '', nick, group_arr);
+                               }
+                               
+                               break;
+                       
+                       // Buddy edit
+                       case 'modify':
+                               if(exists(roster_item))
+                                       sendRoster(xid, '', nick, group_arr);
+                               
+                               break;
+                       
+                       // Buddy delete
+                       case 'delete':
+                               if(exists(roster_item))
+                                       sendRoster(xid, 'remove');
+                               
+                               break;
+               }
+       });
+       
+       // Close the popup
+       closeRosterX();
+}
+
+// Plugin launcher
+function launchRosterX() {
+       // Click events
+       $('#rosterx .bottom .finish').click(function() {
+               if($(this).is('.save'))
+                       return saveRosterX();
+               if($(this).is('.cancel'))
+                       return closeRosterX();
+       });
+       
+       $('#rosterx .rosterx-head a').click(function() {
+               if($(this).is('.check'))
+                       $('#rosterx .results input[type=checkbox]').attr('checked', true);
+               else if($(this).is('.uncheck'))
+                       $('#rosterx .results input[type=checkbox]').removeAttr('checked');
+               
+               return false;
+       });
+}
diff --git a/jappixmini/jappix/js/search.js b/jappixmini/jappix/js/search.js
new file mode 100644 (file)
index 0000000..75b1dfd
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+
+Jappix - An open social platform
+These are the seach tools JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 19/03/11
+
+*/
+
+// Searches in the user's buddy list
+function processBuddySearch(query) {
+       // No query submitted?
+       if(!query)
+               return;
+       
+       // Wildcard (*) submitted
+       if(query == '*')
+               query = '';
+       
+       // Replace forbidden characters in regex
+       query = escapeRegex(query);
+       
+       // Create an empty array
+       var results = new Array();
+       
+       // Search regex
+       var regex = new RegExp('((^)|( ))' + query, 'gi');
+       
+       // Search in the roster
+       var buddies = getAllBuddies();
+       
+       for(i in buddies) {
+               var xid = buddies[i];
+               var nick = getBuddyName(xid);
+               
+               // Buddy match our search, and not yet in the array
+               if(nick.match(regex) && !existArrayValue(results, xid))
+                       results.push(xid);
+       }
+       
+       // Return the results array
+       return results;
+}
+
+// Resets the buddy search tool
+function resetBuddySearch(destination) {
+       $(destination + ' ul').remove();
+       $(destination + ' input').removeClass('suggested');
+}
+
+// Add the clicked XID to the input
+function addBuddySearch(destination, xid) {
+       // Remove the search tool
+       resetBuddySearch(destination);
+       
+       // Define a selector
+       var input = $(destination + ' input');
+       var value = input.val();
+       
+       // Get the old value (if there's another value)
+       var old = '';
+       
+       if(value.match(/(^(.+)(,)(\s)?)(\w+)$/))
+               old = RegExp.$1;
+       
+       // Add the XID to the "to" input and focus on it
+       $(document).oneTime(10, function() {
+               input.val(old + xid).focus();
+       });
+       
+       return false;
+}
+
+// Creates the appropriate markup for the search results
+function createBuddySearch(destination) {
+       // Reset the search engine
+       resetBuddySearch(destination);
+       
+       // Get the entered value
+       var value = $(destination + ' input').val();
+       
+       // Separation with a comma?
+       if(value.match(/^(.+)((,)(\s)?)(\w+)$/))
+               value = RegExp.$5;
+       
+       // Get the result array
+       var entered = processBuddySearch(value);
+       
+       // Display each result (if any)
+       if(entered && entered.length) {
+               // Set a special class to the search input
+               $(destination + ' input').addClass('suggested');
+               
+               // Append each found buddy in the container 
+               var regex = new RegExp('((^)|( ))' + value, 'gi');
+               
+               // Initialize the code generation
+               var code = '<ul>';
+               
+               for(b in entered) {
+                       // Get some values from the XID
+                       var current = getBuddyName(entered[b]).htmlEnc();
+                       current = current.replace(regex, '<b>$&</b>');
+                       
+                       // Add the current element to the global code
+                       code += '<li onclick="return addBuddySearch(\'' + encodeOnclick(destination) + '\', \'' + encodeOnclick(entered[b]) + '\');" data-xid="' + encodeQuotes(entered[b]) + '">' + current + '</li>';
+               }
+               
+               // Finish the code generation
+               code += '</ul>';
+               
+               // Creates the code in the DOM
+               $(destination).append(code);
+               
+               // Put the hover on the first element
+               $(destination + ' ul li:first').addClass('hovered');
+               
+               // Hover event, to not to remove this onblur and loose the click event
+               $(destination + ' ul li').hover(function() {
+                       $(destination + ' ul li').removeClass('hovered');
+                       $(this).addClass('hovered');
+                       
+                       // Add a marker for the blur event
+                       $(destination + ' ul').attr('mouse-hover', 'true');
+               }, function() {
+                       $(this).removeClass('hovered');
+                       
+                       // Remove the mouse over marker
+                       $(destination + ' ul').removeAttr('mouse-hover');
+               });
+       }
+}
+
+// Handles the keyboard arrows press when searching
+function arrowsBuddySearch(e, destination) {
+       // Down arrow: 40
+       // Up arrown: 38
+       
+       // Initialize
+       var code = e.keyCode;
+       
+       // Not the key we want here
+       if((code != 40) && (code != 38))
+               return;
+       
+       // Remove the eventual mouse hover marker
+       $(destination + ' ul').removeAttr('mouse-hover');
+       
+       // Create the path & get its size
+       var path = destination + ' ul li';
+       var pSize = $(path).size();
+       
+       // Define the i value
+       var i = 0;
+       
+       // Switching yet launched
+       if(exists(path + '.hovered')) {
+               var index = $(path).attr('data-hovered');
+               
+               if(index)
+                       i = parseInt(index);
+               
+               if(code == 40)
+                       i++;
+               else
+                       i--;
+       }
+       
+       else if(code == 38)
+               i = pSize - 1;
+       
+       // We must not override the maximum i limit
+       if(i >= pSize)
+               i = 0;
+       
+       // We must not have negative i
+       else if(i < 0)
+               i = pSize - 1;
+       
+       // Modify the list
+       $(path + '.hovered').removeClass('hovered');
+       $(path).eq(i).addClass('hovered');
+       
+       // Store the i index
+       $(path).attr('data-hovered', i);
+       
+       return false;
+}
+
+// Filters the buddies in the roster
+var SEARCH_FILTERED = false;
+
+function goFilterBuddySearch(vFilter) {
+       // Put a marker
+       SEARCH_FILTERED = true;
+       
+       // Show the buddies that match the search string
+       var rFilter = processBuddySearch(vFilter);
+       
+       // Hide all the buddies
+       $('#buddy-list .buddy').hide();
+       
+       // Only show the buddies which match the search
+       for(i in rFilter) {
+               // Choose the correct selector for this search
+               if(!BLIST_ALL)
+                       $('#buddy-list .buddy[data-xid=' + escape(rFilter[i]) + ']:not(.hidden-buddy)').show();
+               else
+                       $('#buddy-list .buddy[data-xid=' + escape(rFilter[i]) + ']').show();
+       }
+}
+
+// Resets the buddy filtering in the roster
+function resetFilterBuddySearch() {
+       // Remove the marker
+       SEARCH_FILTERED = false;
+       
+       // Show all the buddies
+       $('#buddy-list .buddy').show();
+       
+       // Only show available buddies
+       if(!BLIST_ALL)
+               $('#buddy-list .buddy.hidden-buddy').hide();
+       
+       // Update the groups
+       updateGroups();
+}
+
+// Funnels the buddy filtering
+function funnelFilterBuddySearch(keycode) {
+       // Get the input value
+       var input = $('#buddy-list .filter input');
+       var cancel = $('#buddy-list .filter a');
+       var value = input.val();
+       
+       // Security: reset all the groups, empty or not, deployed or not
+       $('#buddy-list .one-group, #buddy-list .group-buddies').show();
+       $('#buddy-list .group span').text('-');
+       
+       // Nothing is entered, or escape pressed
+       if(!value || (keycode == 27)) {
+               if(keycode == 27)
+                       input.val('');
+               
+               resetFilterBuddySearch();
+               cancel.hide();
+       }
+       
+       // Process the filtering
+       else {
+               cancel.show();
+               goFilterBuddySearch(value);
+       }
+       
+       // Update the groups
+       updateGroups();
+}
+
+// Searches for the nearest element (with a lower stamp than the current one)
+function sortElementByStamp(stamp, element) {
+       var array = new Array();
+       var i = 0;
+       var nearest = 0;
+       
+       // Add the stamp values to the array
+       $(element).each(function() {
+               var current_stamp = parseInt($(this).attr('data-stamp'));
+               
+               // Push it!
+               array.push(current_stamp);
+       });
+       
+       // Sort the array
+       array.sort();
+       
+       // Get the nearest stamp value
+       while(stamp > array[i]) {
+               nearest = array[i];
+               
+               i++;
+       }
+       
+       return nearest;
+}
diff --git a/jappixmini/jappix/js/smileys.js b/jappixmini/jappix/js/smileys.js
new file mode 100644 (file)
index 0000000..62b405f
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+
+Jappix - An open social platform
+These are the smileys JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 21/03/11
+
+*/
+
+// Generates the correct HTML code for an emoticon insertion tool
+function emoteLink(smiley, image, hash) {
+       return '<a href="#" class="emoticon emoticon-' + image + ' smileys-images" data-smiley="' + smiley + '"></a>';
+}
+
+// Emoticon links arrays
+function smileyLinks(hash) {
+       var links = '';
+       
+       var sArray = new Array(
+               ':-D',
+               ']:->',
+               '8-)',
+               ':-P',
+               ':-)',
+               ';-)',
+               ':-$',
+               ':-|',
+               ':-/',
+               '=-O',
+               ':-(',
+               ':\'-(',
+               ':-@',
+               ':-!',
+               '({)',
+               '(})',
+               ':3',
+               '(@)',
+               ':-[',
+               ':-{}',
+               '<3',
+               '</3',
+               '@}->--',
+               '(W)',
+               '(Y)',
+               '(N)',
+               '(I)',
+               '(C)',
+               '(D)',
+               '(B)',
+               '(Z)',
+               '(X)',
+               '(P)',
+               '(T)',
+               '(8)',
+               '(%)',
+               '(E)',
+               '(R)',
+               '(*)',
+               '(S)'
+       );
+       
+       var cArray = new Array(
+               'biggrin',
+               'devil',
+               'coolglasses',
+               'tongue',
+               'smile',
+               'wink',
+               'blush',
+               'stare',
+               'frowning',
+               'oh',
+               'unhappy',
+               'cry',
+               'angry',
+               'puke',
+               'hugright',
+               'hugleft',
+               'lion',
+               'pussy',
+               'bat',
+               'kiss',
+               'heart',
+               'brheart',
+               'flower',
+               'brflower',
+               'thumbup',
+               'thumbdown',
+               'lamp',
+               'coffee',
+               'drink',
+               'beer',
+               'boy',
+               'girl',
+               'photo',
+               'phone',
+               'music',
+               'cuffs',
+               'mail',
+               'rainbow',
+               'star',
+               'moon'
+       );
+       
+       for(i in sArray)
+               links += emoteLink(sArray[i], cArray[i], hash);
+       
+       return links;
+}
diff --git a/jappixmini/jappix/js/storage.js b/jappixmini/jappix/js/storage.js
new file mode 100644 (file)
index 0000000..36cf544
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+
+Jappix - An open social platform
+These are the storage JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Gets the storage items of the user
+function getStorage(type) {
+       /* REF: http://xmpp.org/extensions/xep-0049.html */
+       
+       var iq = new JSJaCIQ();
+       iq.setType('get');
+       
+       var iqQuery = iq.setQuery(NS_PRIVATE);
+       iqQuery.appendChild(iq.buildNode('storage', {'xmlns': type}));
+       
+       con.send(iq, handleStorage);
+}
+
+// Handles the storage items
+function handleStorage(iq) {
+       var handleXML = iq.getQuery();
+       var handleFrom = fullXID(getStanzaFrom(iq));
+       
+       // Define some vars
+       var options = $(handleXML).find('storage[xmlns=' + NS_OPTIONS + ']');
+       var inbox = $(handleXML).find('storage[xmlns=' + NS_INBOX + ']');
+       var bookmarks = $(handleXML).find('storage[xmlns=' + NS_BOOKMARKS + ']');
+       var rosternotes = $(handleXML).find('storage[xmlns=' + NS_ROSTERNOTES + ']');
+       
+       // No options and node not yet configured
+       if(options.size() && !options.find('option').size() && (iq.getType() != 'error'))
+               openWelcome();
+       
+       // Parse the options xml
+       options.find('option').each(function() {
+               // We retrieve the informations
+               var type = $(this).attr('type');
+               var value = $(this).text();
+               
+               // We display the storage
+               setDB('options', type, value);
+               
+               // If this is the buddy list show status
+               if((type == 'roster-showall') && (value == '1'))
+                       showAllBuddies('storage');
+       });
+       
+       // Parse the inbox xml
+       inbox.find('message').each(function() {
+               storeInboxMessage(
+                                 $(this).attr('from'),
+                                 $(this).attr('subject'),
+                                 $(this).text(),
+                                 $(this).attr('status'),
+                                 $(this).attr('id'),
+                                 $(this).attr('date'),
+                                 [
+                                  $(this).attr('file_title'),
+                                  $(this).attr('file_href'),
+                                  $(this).attr('file_type'),
+                                  $(this).attr('file_length')
+                                 ]
+                                );
+       });
+       
+       // Parse the bookmarks xml
+       bookmarks.find('conference').each(function() {
+               // We retrieve the informations
+               var xid = $(this).attr('jid');
+               var name = $(this).attr('name');
+               var autojoin = $(this).attr('autojoin');
+               var password = $(this).find('password').text();
+               var nick = $(this).find('nick').text();
+               
+               // We display the storage
+               displayFavorites(xid, name, nick, autojoin, password);
+               
+               // Join the chat if autojoin is enabled
+               if(autojoin == '1')
+                       checkChatCreate(xid, 'groupchat', nick, password, name);
+       });
+       
+       // Parse the roster notes xml
+       rosternotes.find('note').each(function() {
+               setDB('rosternotes', $(this).attr('jid'), $(this).text());
+       });
+       
+       // Options received
+       if(options.size()) {
+               logThis('Options received.');
+               
+               // Now, get the inbox
+               getStorage(NS_INBOX);
+               
+               // Geolocate the user
+               geolocate();
+               
+               $('.options-hidable').show();
+       }
+       
+       // Inbox received
+       else if(inbox.size()) {
+               logThis('Inbox received.');
+               
+               // Send the first presence!
+               firstPresence(getDB('checksum', 1));
+               
+               // Check we have new messages (play a sound if any unread messages)
+               if(checkInboxMessages())
+                       soundPlay(2);
+               
+               $('.inbox-hidable').show();
+       }
+       
+       // Bookmarks received
+       else if(bookmarks.size()) {
+               // Join the groupchats the admin defined (if any)
+               joinConfGroupchats();
+               
+               logThis('Bookmarks received.');
+       }
+       
+       // Roster notes received (for logger)
+       else if(rosternotes.size())
+               logThis('Roster notes received.');
+}
diff --git a/jappixmini/jappix/js/talk.js b/jappixmini/jappix/js/talk.js
new file mode 100644 (file)
index 0000000..7e1320e
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+
+Jappix - An open social platform
+These are the talkpage JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 06/05/11
+
+*/
+
+// Creates the talkpage events
+function eventsTalkPage() {
+       // Launch all associated plugins
+       launchMicroblog();
+       launchRoster();
+       launchPresence();
+       launchPEP();
+       launchNotifications();
+       launchMusic();
+}
+
+// Creates the talkpage code
+function createTalkPage() {
+       // Talkpage exists?
+       if(exists('#talk'))
+               return false;
+       
+       // Anonymous detector
+       var anonymous = isAnonymous();
+       
+       // Generate the HTML code
+       var html = 
+       '<div id="talk" class="removable">' + 
+               '<div id="top-content">' + 
+                       '<div class="tools tools-logo talk-images"></div>' + 
+                       
+                       '<div class="tools tools-all">';
+                               
+                               if(!anonymous) html += 
+                               '<a href="#" onclick="return openInbox();" class="inbox-hidable">' + _e("Messages") +  '</a>' + 
+                               '<a href="#" onclick="return openVCard();">' + _e("Profile") +  '</a>' + 
+                               '<a href="#" onclick="return optionsOpen();" class="options-hidable">' + _e("Options") +  '</a>' + 
+                               '<a href="#" onclick="return normalQuit();">' + _e("Disconnect") +  '</a>';
+                               
+                               else html +=
+                               '<a href="./">' + _e("Disconnect") +  '</a>';
+                       
+                       html +=
+                       '</div>';
+                       
+                       if(!anonymous && document.createElement('audio').canPlayType) html += 
+                       '<div class="tools-all ibubble">' + 
+                               '<div class="tools music talk-images" onclick="return openMusic();"></div>' + 
+                               
+                               '<div class="music-content tools-content bubble hidable">' + 
+                                       '<div class="tools-content-subarrow talk-images"></div>' + 
+                                       
+                                       '<div class="tools-content-subitem">' + 
+                                               '<div class="player">' + 
+                                                       '<a href="#" class="stop talk-images" onclick="return actionMusic(\'stop\');"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="list">' + 
+                                                       '<p class="no-results">' + _e("No result!") +  '</p>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="search">' + 
+                                                       '<input type="text" />' + 
+                                               '</div>' + 
+                                       '</div>' + 
+                               '</div>' + 
+                       '</div>';
+                       
+                       if(!anonymous) html += 
+                       '<div class="tools-all ibubble">' + 
+                               '<div class="tools notifications talk-images" onclick="return showBubble(\'.notifications-content\');"></div>' + 
+                               
+                               '<div class="notifications-content tools-content bubble hidable">' + 
+                                       '<div class="tools-content-subarrow talk-images"></div>' + 
+                                       
+                                       '<div class="tools-content-subitem">' + 
+                                               '<a class="empty" href="#" onclick="return clearNotifications();">' + _e("Empty") +  '</a>' + 
+                                               '<p class="nothing">' + _e("No notifications.") +  '</p>' + 
+                                       '</div>' + 
+                               '</div>' + 
+                       '</div>';
+               
+               html +=
+               '</div>' + 
+               
+               '<div id="main-content">' + 
+                       '<div id="left-content">';
+                               if(!anonymous) html += 
+                               '<div id="buddy-list">' + 
+                                       '<div class="content"></div>' + 
+                                       
+                                       '<div class="filter">' + 
+                                               '<input type="text" placeholder="' + _e("Filter") +  '" />' + 
+                                               '<a href="#">x</a>' + 
+                                       '</div>' + 
+                                       
+                                       '<div class="foot ibubble">' + 
+                                               '<div class="buddy-list-add buddy-list-icon">' + 
+                                                       '<a href="#" class="add talk-images" title="' + _e("Add a friend") +  '"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="buddy-list-join buddy-list-icon">' + 
+                                                       '<a href="#" class="join talk-images" title="' + _e("Join a chat") +  '"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="buddy-list-groupchat buddy-list-icon">' + 
+                                                       '<a href="#" class="groupchat talk-images" title="' + _e("Your groupchats") +  '"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="buddy-list-more buddy-list-icon">' + 
+                                                       '<a href="#" class="more talk-images" title="' + _e("More stuff") +  '"></a>' + 
+                                               '</div>' + 
+                                               
+                                               '<div style="clear: both;"></div>' + 
+                                       '</div>' + 
+                               '</div>';
+                               
+                               html +=
+                               '<div id="my-infos">' + 
+                                       '<div class="content">' + 
+                                               '<div class="element f-presence ibubble">' + 
+                                                       '<a href="#" class="icon picker disabled" data-value="available">' + 
+                                                               '<span class="talk-images"></span>' + 
+                                                       '</a>' + 
+                                                       
+                                                       '<input id="presence-status" type="text" placeholder="' + _e("Status") + '" disabled="" />' + 
+                                               '</div>';
+                                               
+                                               if(!anonymous) html += 
+                                               '<div class="element f-mood pep-hidable ibubble">' + 
+                                                       '<a href="#" class="icon picker" data-value="happy">' + 
+                                                               '<span class="talk-images"></span>' + 
+                                                       '</a>' + 
+                                                       
+                                                       '<input id="mood-text" type="text" placeholder="' + _e("Mood") + '" />' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="element f-activity pep-hidable ibubble">' + 
+                                                       '<a href="#" class="icon picker" data-value="exercising">' + 
+                                                               '<span class="talk-images activity-exercising"></span>' + 
+                                                       '</a>' + 
+                                                       
+                                                       '<input id="activity-text" type="text" placeholder="' + _e("Activity") + '" />' + 
+                                               '</div>';
+                                       
+                                       html +=
+                                       '</div>' + 
+                               '</div>' + 
+                       '</div>' + 
+                       
+                       '<div id="right-content">' + 
+                               '<div id="page-switch">' + 
+                                       '<div class="chans">';
+                                               if(!anonymous) html += 
+                                               '<div class="channel switcher activechan" onclick="return switchChan(\'channel\');">' + 
+                                                       '<div class="icon talk-images"></div>' + 
+                                               
+                                                       '<div class="name">' + _e("Channel") +  '</div>' + 
+                                               '</div>';
+                                       
+                                       html +=
+                                       '</div>' + 
+                                       
+                                       '<div class="more ibubble">' + 
+                                               '<div class="more-button talk-images" onclick="return loadChatSwitch();" title="' + _e("All tabs") +  '"></div>' + 
+                                       '</div>' + 
+                               '</div>' + 
+                               
+                               '<div id="page-engine">';
+                                       if(!anonymous) html += 
+                                       '<div id="channel" class="page-engine-chan" style="display: block;">' + 
+                                               '<div class="top mixed ' + hex_md5(getXID()) + '">' + 
+                                                       '<div class="avatar-container">' + 
+                                                               '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                                                       '</div>' + 
+                                                       
+                                                       '<div class="update">' + 
+                                                               '<p>' + _e("What\'s up with you?") +  '</p>' + 
+                                                               
+                                                               '<div class="microblog-body">' + 
+                                                                       '<input class="focusable" type="text" name="microblog_body" placeholder="' + _e("Type something you want to share with your friends...") + '" disabled="" />' + 
+                                                               '</div>' + 
+                                                               
+                                                               '<div class="one-microblog-icon ibubble">' + 
+                                                                       '<a href="#" onclick="return showBubble(\'#attach\');" title="' + _e("Attach a file") +  '" class="postit attach talk-images"></a>' + 
+                                                                       
+                                                                       '<form id="attach" class="bubble hidable" action="./php/file-share.php" method="post" enctype="multipart/form-data">' + 
+                                                                               '<div class="attach-subarrow talk-images"></div>' + 
+                                                                               
+                                                                               '<div class="attach-subitem">' + 
+                                                                                       '<p class="attach-p">' + _e("Attach a file") +  '</p>' + 
+                                                                                       generateFileShare() + 
+                                                                               '</div>' + 
+                                                                       '</form>' + 
+                                                               '</div>' + 
+                                                       '</div>' + 
+                                               '</div>' + 
+                                               
+                                               '<div class="content mixed"></div>' + 
+                                               
+                                               '<div class="footer">' + 
+                                                       '<div class="sync talk-images">' + _e("You are synchronized with your network.") +  '</div>' + 
+                                                       
+                                                       '<div class="unsync talk-images">' + _e("Cannot send anything: you can only receive notices!") +  '</div>' + 
+                                                       
+                                                       '<div class="fetch wait-small">' + _e("Fetching the social channel...") +  '</div>' + 
+                                               '</div>' + 
+                                       '</div>';
+                               
+                               html +=
+                               '</div>' + 
+                       '</div>' + 
+               '</div>' + 
+       '</div>';
+       
+       // Create the HTML code
+       $('body').prepend(html);
+       
+       // Adapt the buddy-list size
+       adaptRoster();
+       
+       // Create JS events
+       eventsTalkPage();
+       
+       // Start the auto idle functions
+       liveIdle();
+       
+       return true;
+}
+
+// Destroys the talkpage code
+function destroyTalkPage() {
+       // Reset our database
+       resetDB();
+       
+       // Reset some vars
+       STANZA_ID = 1;
+       BLIST_ALL = false;
+       FIRST_PRESENCE_SENT = false;
+       SEARCH_FILTERED = false;
+       AVATAR_PENDING = [];
+       
+       // Kill all timers, exept the board ones
+       $('*:not(#board .one-board)').stopTime();
+       
+       // Kill the auto idle functions
+       dieIdle();
+       
+       // We renitalise the html markup as its initiale look
+       $('.removable').remove();
+       pageTitle('home');
+       
+       // Finally we show the homepage
+       $('#home').show();
+}
diff --git a/jappixmini/jappix/js/tooltip.js b/jappixmini/jappix/js/tooltip.js
new file mode 100644 (file)
index 0000000..2ba87ab
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+
+Jappix - An open social platform
+These are the tooltip JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/08/11
+
+*/
+
+// Creates a tooltip code
+function createTooltip(xid, hash, type) {
+       // Path to the element
+       var path = '#' + hash;
+       var path_tooltip = path + ' .chat-tools-' + type;
+       var path_bubble = path_tooltip + ' .bubble-' + type;
+       
+       // Yet exists?
+       if(exists(path_bubble))
+               return false;
+       
+       // Generates special tooltip HTML code
+       var title = '';
+       var content = '';
+       
+       switch(type) {
+               // Smileys
+               case 'smileys':
+                       title = _e("Smiley insertion");
+                       content = smileyLinks(hash);
+                       
+                       break;
+               
+               // Style
+               case 'style':
+                       title = _e("Change style");
+                       content = 
+                               '<label class="bold"><input type="checkbox" class="bold" />' + _e("Text in bold") + '</label>' + 
+                               '<label class="italic"><input type="checkbox" class="italic" />' + _e("Text in italic") + '</label>' + 
+                               '<label class="underline"><input type="checkbox" class="underline" />' + _e("Underlined text") + '</label>' + 
+                               '<a href="#" class="color" style="background-color: #b10808; clear: both;" data-color="b10808"></a>' + 
+                               '<a href="#" class="color" style="background-color: #e5860c;" data-color="e5860c"></a>' + 
+                               '<a href="#" class="color" style="background-color: #f0f30e;" data-color="f0f30e"></a>' + 
+                               '<a href="#" class="color" style="background-color: #009a04;" data-color="009a04"></a>' + 
+                               '<a href="#" class="color" style="background-color: #0ba9a0;" data-color="0ba9a0"></a>' + 
+                               '<a href="#" class="color" style="background-color: #04228f;" data-color="04228f"></a>' + 
+                               '<a href="#" class="color" style="background-color: #9d0ab7;" data-color="9d0ab7"></a>' + 
+                               '<a href="#" class="color" style="background-color: #8a8a8a;" data-color="8a8a8a"></a>';
+                       
+                       break;
+               
+               // File send
+               case 'file':
+                       title = _e("Send a file");
+                       content = '<p style="margin-bottom: 8px;">' + _e("Once uploaded, your friend will be prompted to download the file you sent.") + '</p>';
+                       content += '<form id="oob-upload" action="./php/send.php" method="post" enctype="multipart/form-data">' + generateFileShare() + '</form>';
+                       
+                       break;
+               
+               // Chat log
+               case 'save':
+                       title = _e("Save chat");
+                       content = '<p style="margin-bottom: 8px;">' + _e("Click on the following link to get the chat log, and wait. Then click again to get the file.") + '</p>';
+                       
+                       // Possible to generate any log?
+                       if($(path + ' .one-line').size())
+                               content += '<a href="#" class="tooltip-actionlog">' + _e("Generate file!") + '</a>';
+                       else
+                               content += '<span class="tooltip-nolog">' + _e("This chat is empty!") + '</span>';
+                       
+                       break;
+       }
+       
+       // Generates general tooltip HTML code
+       var html = 
+               '<div class="tooltip bubble-' + type + '">' + 
+                       '<div class="tooltip-subitem">' + 
+                               '<p class="tooltip-top">' + title + '</p>' + 
+                               content + 
+                       '</div>' + 
+                       
+                       '<div class="tooltip-subarrow talk-images"></div>' + 
+               '</div>';
+       
+       // Append the HTML code
+       $(path_tooltip).append(html);
+       
+       // Special events
+       switch(type) {
+               // Smileys
+               case 'smileys':
+                       // Apply click event on smiley links
+                       $(path_tooltip + ' a.emoticon').click(function() {
+                               return insertSmiley($(this).attr('data-smiley'), hash);
+                       });
+                       
+                       break;
+               
+               // Style
+               case 'style':
+                       // Paths to items
+                       var message_area = path + ' .message-area';
+                       var bubble_style = path_tooltip + ' .bubble-style ';
+                       var style = bubble_style + 'input:checkbox';
+                       var colors = bubble_style + 'a.color';
+                       
+                       // Click event on color picker
+                       $(colors).click(function() {
+                               // The clicked color is yet selected
+                               if($(this).hasClass('selected')) {
+                                       $(message_area).removeAttr('data-color');
+                                       $(this).removeClass('selected');
+                               }
+                               
+                               else {
+                                       $(message_area).attr('data-color', $(this).attr('data-color'));
+                                       $(colors).removeClass('selected');
+                                       $(this).addClass('selected');
+                               }
+                               
+                               return false;
+                       });
+                       
+                       // Change event on text style checkboxes
+                       $(style).change(function() {
+                               // Get current type
+                               var style_data = 'data-' + $(this).attr('class');
+                               
+                               // Checked checkbox?
+                               if($(this).filter(':checked').size())
+                                       $(message_area).attr(style_data, true);
+                               else
+                                       $(message_area).removeAttr(style_data);
+                       });
+                       
+                       // Update the textarea style when it is changed
+                       $(style + ', ' + colors).click(function() {
+                               var style = generateStyle(hash);
+                               
+                               // Any style to apply?
+                               if(style)
+                                       $(message_area).attr('style', style);
+                               else
+                                       $(message_area).removeAttr('style');
+                               
+                               // Focus again on the message textarea
+                               $(document).oneTime(10, function() {
+                                       $(message_area).focus();
+                               });
+                       });
+                       
+                       // Load current style
+                       loadStyleSelector(hash);
+                       
+                       break;
+               
+               // File send
+               case 'file':
+                       // File upload vars
+                       var oob_upload_options = {
+                               dataType:       'xml',
+                               beforeSubmit:   waitUploadOOB,
+                               success:        handleUploadOOB
+                       };
+                       
+                       // Upload form submit event
+                       $(path_tooltip + ' #oob-upload').submit(function() {
+                               if($(path_tooltip + ' #oob-upload input[type=file]').val())
+                                       $(this).ajaxSubmit(oob_upload_options);
+                               
+                               return false;
+                       });
+                       
+                       // Upload input change event
+                       $(path_tooltip + ' #oob-upload input[type=file]').change(function() {
+                               if($(this).val())
+                                       $(path_tooltip + ' #oob-upload').ajaxSubmit(oob_upload_options);
+                               
+                               return false;
+                       });
+                       
+                       // Input click event
+                       $(path_tooltip + ' #oob-upload input[type=file], ' + path_tooltip + ' #oob-upload input[type=submit]').click(function() {
+                               if(exists(path_tooltip + ' #oob-upload input[type=reset]'))
+                                       return;
+                               
+                               // Lock the bubble
+                               $(path_bubble).addClass('locked');
+                               
+                               // Add a cancel button
+                               $(this).after('<input type="reset" value="' + _e("Cancel") + '" />');
+                               
+                               // Cancel button click event
+                               $(path_tooltip + ' #oob-upload input[type=reset]').click(function() {
+                                       // Remove the bubble
+                                       $(path_bubble).removeClass('locked');
+                                       destroyTooltip(hash, 'file');
+                               });
+                       });
+                       
+                       break;
+               
+               // Chat log
+               case 'save':
+                       // Chat log generation click event
+                       $(path_tooltip + ' .tooltip-actionlog').click(function() {
+                               // Replace it with a waiting notice
+                               $(this).replaceWith('<span class="tooltip-waitlog">' + _e("Please wait...") + '</span>');
+                               
+                               generateChatLog(xid, hash);
+                               
+                               return false;
+                       });
+                       
+                       break;
+       }
+       
+       return true;
+}
+
+// Destroys a tooltip code
+function destroyTooltip(hash, type) {
+       $('#' + hash + ' .chat-tools-content:not(.mini) .bubble-' + type + ':not(.locked)').remove();
+}
+
+// Applies the page-engine tooltips hover event
+function hoverTooltip(xid, hash, type) {
+       $('#' + hash + ' .chat-tools-' + type).hover(function() {
+               createTooltip(xid, hash, type);
+       }, function() {
+               destroyTooltip(hash, type)
+       });
+}
+
+// Applies the hoverTooltip function to the needed things
+function tooltipIcons(xid, hash) {
+       // Hover events
+       hoverTooltip(xid, hash, 'smileys');
+       hoverTooltip(xid, hash, 'style');
+       hoverTooltip(xid, hash, 'file');
+       hoverTooltip(xid, hash, 'save');
+       
+       // Click events
+       $('#' + hash + ' a.chat-tools-content, #' + hash + ' .chat-tools-content a').click(function() {
+               return false;
+       });
+}
+
+// Loads the style selector options
+function loadStyleSelector(hash) {
+       // Define the vars
+       var path = '#' + hash;
+       var message_area = $(path + ' .message-area');
+       var bubble_style = path + ' .bubble-style';
+       
+       // Apply the options to the style selector
+       $(bubble_style + ' input[type=checkbox]').each(function() {
+               // Current input enabled?
+               if(message_area.attr('data-' + $(this).attr('class')))
+                       $(this).attr('checked', true);
+       });
+       
+       // Apply message color
+       $(bubble_style + ' a.color[data-color=' + message_area.attr('data-color') + ']').addClass('selected');
+}
diff --git a/jappixmini/jappix/js/userinfos.js b/jappixmini/jappix/js/userinfos.js
new file mode 100644 (file)
index 0000000..35a58fe
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+
+Jappix - An open social platform
+These are the user-infos JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/03/11
+
+*/
+
+// Opens the user-infos popup
+function openUserInfos(xid) {
+       // Can show shortcuts?
+       var shortcuts = '';
+       
+       if(xid != getXID()) {
+               shortcuts = '<div class="shortcuts">' + 
+                                       '<a href="#" class="message talk-images" title="' + _e("Send him/her a message") + '" onclick="closeUserInfos(); return composeInboxMessage(\'' + encodeOnclick(xid) + '\');"></a>' + 
+                                       '<a href="#" class="chat talk-images" title="' + _e("Start a chat with him/her") + '" onclick="closeUserInfos(); return checkChatCreate(\'' + encodeOnclick(xid) + '\', \'chat\');"></a>' + 
+                                       '<a href="#" class="command talk-images" title="' + _e("Command") + '" onclick="closeUserInfos(); return retrieveAdHoc(\'' + encodeOnclick(xid) + '\');"></a>' + 
+                            '</div>';
+       }
+       
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("User profile") + '</div>' + 
+       
+       '<div class="tab">' + 
+               '<a href="#" class="tab-active" data-key="1">' + _e("General") + '</a>' + 
+               '<a href="#" data-key="2">' + _e("Advanced") + '</a>' + 
+               '<a href="#" data-key="3">' + _e("Comments") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="lap-active one-lap info1">' + 
+                       '<div class="main-infos">' + 
+                               '<div class="avatar-container">' + 
+                                       '<img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" />' + 
+                               '</div>' + 
+                               
+                               '<h1 id="BUDDY-FN" class="reset-info">' + _e("unknown") + '</h1>' + 
+                               '<h2 class="buddy-xid" class="reset-info">' + _e("unknown") + '</h2>' + 
+                               '<h3 class="buddy-last" class="reset-info">' + _e("unknown") + '</h3>' + 
+                               
+                               shortcuts + 
+                       '</div>' + 
+                       
+                       '<div class="block-infos">' + 
+                               '<div class="one-line"><b>' + _e("Date of birth") + '</b><span id="BUDDY-BDAY" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("E-mail") + '</b><span id="BUDDY-EMAIL-USERID" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("Phone") + '</b><span id="BUDDY-TEL-NUMBER" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("Website") + '</b><span id="BUDDY-URL" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                       '</div>' + 
+                       
+                       '<div class="block-infos">' + 
+                               '<div class="one-line"><b>' + _e("Client") + '</b><span id="BUDDY-CLIENT" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("System") + '</b><span id="BUDDY-SYSTEM" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("Local time") + '</b><span id="BUDDY-TIME" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div class="one-lap info2">' + 
+                       '<div class="block-infos">' + 
+                               '<div class="one-line"><b>' + _e("Street") + '</b><span id="BUDDY-ADR-STREET" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("City") + '</b><span id="BUDDY-ADR-LOCALITY" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("Postal code") + '</b><span id="BUDDY-ADR-PCODE" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                               
+                               '<div class="one-line"><b>' + _e("Country") + '</b><span id="BUDDY-ADR-CTRY" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                       '</div>' + 
+                       
+                       '<div class="block-infos">' + 
+                               '<div class="one-line"><b>' + _e("Biography") + '</b><span id="BUDDY-DESC" class="reset-info">' + _e("unknown") + '</span></div>' + 
+                       '</div>' + 
+               '</div>' + 
+               
+               '<div class="one-lap info3">' + 
+                       '<textarea class="rosternotes" rows="8" cols="60"></textarea>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish">' + _e("Close") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('userinfos', html);
+       
+       // Associate the events
+       launchUserInfos();
+       
+       // We retrieve the user's vcard
+       retrieveUserInfos(xid);
+       
+       return false;
+}
+
+// Closes the user-infos popup
+function closeUserInfos() {
+       // Send the buddy comments
+       sendBuddyComments();
+       
+       // Destroy the popup
+       destroyPopup('userinfos');
+       
+       return false;
+}
+
+// Gets the user-infos
+function retrieveUserInfos(xid) {
+       // We setup the waiting indicator
+       markers = 'vcard last';
+       
+       // We put the user's XID
+       $('#userinfos .buddy-xid').text(xid);
+       
+       // We get the vCard
+       getVCard(xid, 'buddy');
+       
+       // Get the highest resource for this XID
+       var cXID = getHighestResource(xid);
+       var pXID = xid;
+       
+       // If the user is logged in
+       if(cXID) {
+               // Change the XID
+               pXID = cXID;
+               
+               // We request the user's system infos
+               queryUserInfos(cXID, 'version')
+               
+               // We request the user's local time
+               queryUserInfos(cXID, 'time')
+               
+               // Add these to the markers
+               markers += ' version time';
+       }
+       
+       // We request the user's last activity
+       queryUserInfos(pXID, 'last');
+       
+       // Add the markers
+       $('#userinfos .content').addClass(markers);
+       
+       // We request all the user's comments
+       displayBuddyComments(xid);
+}
+
+// Builds the asked user-infos query
+function queryUserInfos(xid, mode) {
+       // Generate a session ID
+       var id = genID();
+       $('#userinfos').attr('data-' + mode, id);
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       
+       iq.setID(id);
+       iq.setType('get');
+       iq.setTo(xid);
+       
+       // Last activity query
+       if(mode == 'last') {
+               iq.setQuery(NS_LAST);
+               con.send(iq, lastActivityUserInfos);
+       }
+       
+       // Time query
+       else if(mode == 'time') {
+               iq.appendNode('time', {'xmlns': NS_URN_TIME});
+               con.send(iq, localTimeUserInfos);
+       }
+       
+       // Version query
+       else if(mode == 'version') {
+               iq.setQuery(NS_VERSION);
+               con.send(iq, versionUserInfos);
+       }
+}
+
+// Checks if the waiting item can be hidden
+function vCardBuddyInfos() {
+       $('#userinfos .content').removeClass('vcard');
+       wUserInfos();
+}
+
+// Displays the buddy comments
+function displayBuddyComments(xid) {
+       // We get the value in the database
+       var value = getDB('rosternotes', xid);
+       
+       // Display the value
+       if(value)
+               $('#userinfos .rosternotes').val(value);
+}
+
+// Displays the user's last activity result
+function lastActivityUserInfos(iq) {
+       // Extract the request ID
+       var id = iq.getID();
+       var path = '#userinfos[data-last=' + id + ']';
+       
+       // End if session does not exist
+       if(!exists(path))
+               return;
+       
+       if(iq && (iq.getType() == 'result')) {
+               // Get the values
+               var from = fullXID(getStanzaFrom(iq));
+               var seconds = $(iq.getNode()).find('query').attr('seconds');
+               
+               // Any seconds?
+               if(seconds != undefined) {
+                       // Initialize the parsing
+                       var last;
+                       seconds = parseInt(seconds);
+                       
+                       // Active user
+                       if(seconds <= 60)
+                               last = _e("User currently active");
+                       
+                       // Inactive user
+                       else {
+                               // Parse the date
+                               var date_now = new Date();
+                               var time_now = date_now.getTime();
+                               var date_last = new Date(date_now - (seconds * 1000));
+                               var date = date_last.toLocaleString();
+                               
+                               // Offline user
+                               if(from.indexOf('/') == -1)
+                                       last = printf(_e("Last seen: %s"), date);
+                               
+                               // Online user
+                               else
+                                       last = printf(_e("Inactive since: %s"), date);
+                       }
+                       
+                       // Append this text
+                       $('#userinfos .buddy-last').text(last);
+               }
+               
+               logThis('Last activity received: ' + from);
+       }
+       
+       $('#userinfos .content').removeClass('last');
+       wUserInfos();
+}
+
+// Displays the user's software version result
+function versionUserInfos(iq) {
+       // Extract the request ID
+       var id = iq.getID();
+       var path = '#userinfos[data-version=' + id + ']';
+       
+       // End if session does not exist
+       if(!exists(path))
+               return;
+       
+       // Extract the reply data
+       if(iq && (iq.getType() == 'result')) {
+               // Get the values
+               var xml = iq.getQuery();
+               var name = $(xml).find('name').text();
+               var version = $(xml).find('version').text();
+               var os = $(xml).find('os').text();
+               
+               // Put the values together
+               if(name && version)
+                       name = name + ' ' + version;
+               
+               // Display the values
+               if(name)
+                       $(path + ' #BUDDY-CLIENT').text(name);
+               if(os)
+                       $(path + ' #BUDDY-SYSTEM').text(os);
+               
+               logThis('Software version received: ' + fullXID(getStanzaFrom(iq)));
+       }
+       
+       $('#userinfos .content').removeClass('version');
+       wUserInfos();
+}
+
+// Displays the user's local time result
+function localTimeUserInfos(iq) {
+       // Extract the request ID
+       var id = iq.getID();
+       var path = '#userinfos[data-time=' + id + ']';
+       
+       // End if session does not exist
+       if(!exists(path))
+               return;
+       
+       if(iq && (iq.getType() == 'result')) {
+               // Get the values
+               var xml = iq.getNode();
+               var tzo = $(xml).find('tzo').text();
+               var utc = $(xml).find('utc').text();
+               
+               // Any UTC?
+               if(utc) {
+                       // Add the TZO if there's no one
+                       if(tzo && utc.match(/^(.+)Z$/))
+                               utc = RegExp.$1 + tzo;
+                       
+                       // Get the local date string
+                       var local_string = Date.hrTime(utc);
+                       
+                       // Then display it
+                       $(path + ' #BUDDY-TIME').text(local_string);
+               }
+               
+               logThis('Local time received: ' + fullXID(getStanzaFrom(iq)));
+       }
+       
+       $('#userinfos .content').removeClass('time');
+       wUserInfos();
+}
+
+// Hides the waiting image if needed
+function wUserInfos() {
+       var selector = $('#userinfos .content');
+       
+       if(!selector.hasClass('vcard') && !selector.hasClass('last') && !selector.hasClass('version') && !selector.hasClass('time'))
+               $('#userinfos .wait').hide();
+}
+
+// Sends the buddy comments
+function sendBuddyComments() {
+       // Update the current value
+       var value = $('#userinfos .rosternotes').val();
+       var xid = $('#userinfos .buddy-xid').text();
+       
+       // Necessary to update?
+       var old_value = getDB('rosternotes', xid);
+       
+       if((old_value == value) || (!old_value && !value))
+               return false;
+       
+       // Update the database
+       setDB('rosternotes', xid, value);
+       
+       // Send the new buddy storage values
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       var query = iq.setQuery(NS_PRIVATE);
+       var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_ROSTERNOTES}));
+       
+       // We regenerate the XML
+       for(var i = 0; i < sessionStorage.length; i++) {
+               // Get the pointer values
+               var current = sessionStorage.key(i);
+               
+               // If the pointer is on a stored rosternote
+               if(explodeThis('_', current, 0) == 'rosternotes') {
+                       var xid = explodeThis('_', current, 1);
+                       var value = sessionStorage.getItem(current);
+                       
+                       if(xid && value)
+                               storage.appendChild(iq.buildNode('note', {'jid': xid, 'xmlns': NS_ROSTERNOTES}, value));
+               }
+       }
+       
+       con.send(iq);
+       
+       return false;
+}
+
+// Switches the user-infos tabs
+function switchUInfos(id) {
+       $('#userinfos .content .one-lap').hide();
+       $('#userinfos .content .info' + id).show();
+       $('#userinfos .tab a').removeClass('tab-active');
+       $('#userinfos .tab a[data-key=' + id + ']').addClass('tab-active');
+       
+       return false;
+}
+
+// Gets the user's informations when creating a new chat
+function getUserInfos(hash, xid, nick, type) {
+       // This is a normal chat
+       if(type != 'private') {
+               // Display the buddy name
+               if(nick) {
+                       $('#' + hash + ' .top .name .bc-name').text(nick);
+                       $('#page-switch .' + hash + ' .name').text(nick);
+               }
+               
+               // Get the buddy PEP informations
+               displayAllPEP(xid);
+       }
+       
+       // Display the buddy presence
+       presenceFunnel(xid, hash);
+}
+
+// Plugin launcher
+function launchUserInfos() {
+       // Click events
+       $('#userinfos .tab a').click(function() {
+               // Yet active?
+               if($(this).hasClass('tab-active'))
+                       return false;
+               
+               // Switch to the good tab
+               var key = parseInt($(this).attr('data-key'));
+               
+               return switchUInfos(key);
+       });
+       
+       $('#userinfos .bottom .finish').click(function() {
+               return closeUserInfos();
+       });
+}
diff --git a/jappixmini/jappix/js/utilities.js b/jappixmini/jappix/js/utilities.js
new file mode 100644 (file)
index 0000000..b28a6a7
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+
+Jappix - An open social platform
+These are the utilities JS script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, olivierm
+Last revision: 24/06/11
+
+*/
+
+// Checks if a function exists
+function functionExists(func) {
+       if(typeof func == 'function')
+               return true;
+       
+       return false;
+}
+
+// Returns whether using HTTPS or not
+function isHTTPS() {
+       if(window.location.href && (window.location.href).match(/^https/i))
+               return true;
+       
+       return false;
+}
+
+// Generates the good storage URL
+function generateURL(url) {
+       // HTTPS not allowed
+       if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/))
+               url = 'http' + RegExp.$1;
+       
+       return url;
+}
+
+// Disables an input if needed
+function disableInput(value, condition) {
+       if(value == condition)
+               return ' disabled=""';
+       
+       return '';
+}
+
+// Cuts a string
+function cut(string, limit) {
+       return string.substr(0, limit);
+}
+
+// Truncates a string
+function truncate(string, limit) {
+       // Must truncate the string
+       if(string.length > limit)
+               string = string.substr(0, limit) + '...';
+       
+       return string;
+}
+
+// Removes the new lines
+function noLines(string) {
+       return string.replace(/\n/g, ' ');
+}
+
+// Encodes a string for onclick attribute
+function encodeOnclick(str) {
+       return (encodeQuotes(str)).replace(/'/g, '\\$&');
+}
+
+// Checks if we are in the anonymous mode
+function isAnonymous() {
+       if(allowedAnonymous() && LINK_VARS['r'])
+               return true;
+       
+       return false;
+}
+
+// Checks if this is a private chat user
+function isPrivate(xid) {
+       if(exists('[data-xid=' + escape(xid) + '][data-type=groupchat]'))
+               return true;
+       
+       return false;
+}
+
+// Checks if the user browser is obsolete
+function isObsolete() {
+       // Get browser name & version
+       var browser_name = BrowserDetect.browser;
+       var browser_version = BrowserDetect.version;
+       
+       // No DOM storage
+       if(!hasDB() || !hasPersistent())
+               return true;
+       
+       // Obsolete IE
+       if((browser_name == 'Explorer') && (browser_version < 8))
+               return true;
+       
+       // Obsolete Chrome
+       if((browser_name == 'Chrome') && (browser_version < 7))
+               return true;
+       
+       // Obsolete Safari
+       if((browser_name == 'Safari') && (browser_version < 4))
+               return true;
+       
+       // Obsolete Firefox
+       if((browser_name == 'Firefox') && (browser_version < 3.5))
+               return true;
+       
+       // Obsolete Opera
+       if((browser_name == 'Opera') && (browser_version < 9))
+               return true;
+       
+       return false;
+}
+
+// Gets a MUC user XID
+function getMUCUserXID(room, nick) {
+       return $('div.chat[data-xid=' + escape(room) + '] div[data-nick=' + escape(nick) + ']').attr('data-xid');
+}
+
+// Gets a MUC user read XID
+function getMUCUserRealXID(room, nick) {
+       return $('div.chat[data-xid=' + escape(room) + '] div[data-nick=' + escape(nick) + ']').attr('data-realxid');
+}
+
+// Gets the server of the user
+function getServer() {
+       // Return the domain of the user
+       return con.domain;
+}
+
+// Gets the password of the user
+function getPassword() {
+       // Return the password of the user
+       return con.pass;
+}
+
+// Quotes the nick of an user
+function quoteMyNick(hash, nick) {
+       $(document).oneTime(10, function() {
+               $('#page-engine #' + hash + ' .message-area').val(nick + ', ').focus();
+       });
+}
+
+// Escapes a string for a regex usage
+function escapeRegex(query) {
+       return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
+}
+
+// Converts a XML document to a string
+function xmlToString(xmlData) {
+       try {
+               // For Mozilla, Firefox, Opera, etc.
+               if(window.XMLSerializer)
+                       return (new XMLSerializer()).serializeToString(xmlData);
+               
+               // For Internet Explorer
+               if(window.ActiveXObject)
+                       return xmlData.xml;
+               
+               return null;
+       }
+       
+       catch(e) {
+               return null;
+       }
+}
+
+// Converts a string to a XML document
+function XMLFromString(sXML) {
+       try {
+               // No data?
+               if(!sXML)
+                       return '';
+               
+               // Add the XML tag
+               if(!sXML.match(/^<\?xml/i))
+                       sXML = '<?xml version="1.0"?>' + sXML;
+               
+               // Parse it!
+               if(window.DOMParser)
+                       return (new DOMParser()).parseFromString(sXML, 'text/xml');
+               
+               if(window.ActiveXObject) {
+                       var oXML = new ActiveXObject('Microsoft.XMLDOM');
+                       oXML.loadXML(sXML);
+                       
+                       return oXML;
+               }
+       }
+       
+       catch(e) {
+               return '';
+       }
+}
+
+// Return the file category
+function fileCategory(ext) {
+       var cat;
+       
+       switch(ext) {
+               // Images
+               case 'jpg':
+               case 'jpeg':
+               case 'png':
+               case 'bmp':
+               case 'gif':
+               case 'tif':
+               case 'svg':
+               case 'psp':
+               case 'xcf':
+                       cat = 'image';
+                       
+                       break;
+               
+               // Videos
+               case 'ogv':
+               case 'ogg':
+               case 'mkv':
+               case 'avi':
+               case 'mov':
+               case 'mp4':
+               case 'm4v':
+               case 'wmv':
+               case 'asf':
+               case 'mpg':
+               case 'mpeg':
+               case 'ogm':
+               case 'rmvb':
+               case 'rmv':
+               case 'qt':
+               case 'flv':
+               case 'ram':
+               case '3gp':
+               case 'avc':
+                       cat = 'video';
+                       
+                       break;
+               
+               // Sounds
+               case 'oga':
+               case 'mka':
+               case 'flac':
+               case 'mp3':
+               case 'wav':
+               case 'm4a':
+               case 'wma':
+               case 'rmab':
+               case 'rma':
+               case 'bwf':
+               case 'aiff':
+               case 'caf':
+               case 'cda':
+               case 'atrac':
+               case 'vqf':
+               case 'au':
+               case 'aac':
+               case 'm3u':
+               case 'mid':
+               case 'mp2':
+               case 'snd':
+               case 'voc':
+                       cat = 'audio';
+                       
+                       break;
+               
+               // Documents
+               case 'pdf':
+               case 'odt':
+               case 'ott':
+               case 'sxw':
+               case 'stw':
+               case 'ots':
+               case 'sxc':
+               case 'stc':
+               case 'sxi':
+               case 'sti':
+               case 'pot':
+               case 'odp':
+               case 'ods':
+               case 'doc':
+               case 'docx':
+               case 'docm':
+               case 'xls':
+               case 'xlsx':
+               case 'xlsm':
+               case 'xlt':
+               case 'ppt':
+               case 'pptx':
+               case 'pptm':
+               case 'pps':
+               case 'odg':
+               case 'otp':
+               case 'sxd':
+               case 'std':
+               case 'std':
+               case 'rtf':
+               case 'txt':
+               case 'htm':
+               case 'html':
+               case 'shtml':
+               case 'dhtml':
+               case 'mshtml':
+                       cat = 'document';
+                       
+                       break;
+               
+               // Packages
+               case 'tgz':
+               case 'gz':
+               case 'tar':
+               case 'ar':
+               case 'cbz':
+               case 'jar':
+               case 'tar.7z':
+               case 'tar.bz2':
+               case 'tar.gz':
+               case 'tar.lzma':
+               case 'tar.xz':
+               case 'zip':
+               case 'xz':
+               case 'rar':
+               case 'bz':
+               case 'deb':
+               case 'rpm':
+               case '7z':
+               case 'ace':
+               case 'cab':
+               case 'arj':
+               case 'msi':
+                       cat = 'package';
+                       
+                       break;
+               
+               // Others
+               default:
+                       cat = 'other';
+                       
+                       break;
+       }
+       
+       return cat;
+}
+
+// Registers Jappix as the default XMPP links handler
+function xmppLinksHandler() {
+       try {
+               navigator.registerProtocolHandler('xmpp', JAPPIX_LOCATION + '?x=%s', SERVICE_NAME);
+               
+               return true;
+       }
+       
+       catch(e) {
+               return false;
+       }
+}
+
+// Checks if a value exists in an array
+function existArrayValue(array, value) {
+       try {
+               // Loop in the array
+               for(i in array) {
+                       if(array[i] == value)
+                               return true;
+               }
+               
+               return false;
+       }
+       
+       catch(e) {
+               return false;
+       }
+}
+
+// Removes a value from an array
+function removeArrayValue(array, value) {
+       for(i in array) {
+               // It matches, remove it!
+               if(array[i] == value) {
+                       array.splice(i, 1);
+                       
+                       return true;
+               }
+       }
+       
+       return false;
+}
+
+// Converts a string to an array
+function stringToArray(string) {
+       var array = [];
+       
+       // Any string to convert?
+       if(string) {
+               // More than one item
+               if(string.match(/,/gi)) {
+                       var string_split = string.split(',');
+                       
+                       for(i in string_split) {
+                               if(string_split[i])
+                                       array.push(string_split[i]);
+                               else
+                                       array.push('');
+                       }
+               }
+               
+               // Only one item
+               else
+                       array.push(string);
+       }
+       
+       return array;
+}
+
+// Get the index of an array value
+function indexArrayValue(array, value) {
+       // Nothing?
+       if(!array || !array.length)
+               return 0;
+       
+       // Read the index of the value
+       var index = 0;
+       
+       for(var i = 0; i < array.length; i++) {
+               if(array[i] == value) {
+                       index = i;
+                       
+                       break;
+               }
+       }
+       
+       return index;
+}
diff --git a/jappixmini/jappix/js/vcard.js b/jappixmini/jappix/js/vcard.js
new file mode 100644 (file)
index 0000000..6e0fa09
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+
+Jappix - An open social platform
+These are the vCard JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+// Opens the vCard popup
+function openVCard() {
+       // Popup HTML content
+       var html =
+       '<div class="top">' + _e("Your profile") + '</div>' + 
+       
+       '<div class="tab">' + 
+               '<a href="#" class="tab-active" data-key="1">' + _e("Identity") + '</a>' + 
+               '<a href="#" data-key="2">' + _e("Profile image") + '</a>' + 
+               '<a href="#" data-key="3">' + _e("Others") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="content">' + 
+               '<div id="lap1" class="lap-active one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Personal") + '</legend>' + 
+                               
+                               '<label for="USER-FN">' + _e("Complete name") + '</label>' + 
+                               '<input type="text" id="USER-FN" class="vcard-item" />' + 
+                               
+                               '<label for="USER-NICKNAME">' + _e("Nickname") + '</label>' + 
+                               '<input type="text" id="USER-NICKNAME" class="vcard-item" />' + 
+                               
+                               '<label for="USER-N-GIVEN">' + _e("First name") + '</label>' + 
+                               '<input type="text" id="USER-N-GIVEN" class="vcard-item" />' + 
+                               
+                               '<label for="USER-N-FAMILY">' + _e("Last name") + '</label>' + 
+                               '<input type="text" id="USER-N-FAMILY" class="vcard-item" />' + 
+                               
+                               '<label for="USER-BDAY">' + _e("Date of birth") + '</label>' + 
+                               '<input type="text" id="USER-BDAY" class="vcard-item" />' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Contact") + '</legend>' + 
+                               
+                               '<label for="USER-EMAIL-USERID">' + _e("E-mail") + '</label>' + 
+                               '<input type="text" id="USER-EMAIL-USERID" class="vcard-item" />' + 
+                               
+                               '<label for="USER-TEL-NUMBER">' + _e("Phone") + '</label>' + 
+                               '<input type="text" id="USER-TEL-NUMBER" class="vcard-item" />' + 
+                               
+                               '<label for="USER-URL">' + _e("Website") + '</label>' + 
+                               '<input type="text" id="USER-URL" class="vcard-item" />' + 
+                       '</fieldset>' + 
+               '</div>' + 
+               
+               '<div id="lap2" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("New") + '</legend>' + 
+                               
+                               '<input type="hidden" id="USER-PHOTO-TYPE" class="vcard-item" />' + 
+                               '<input type="hidden" id="USER-PHOTO-BINVAL" class="vcard-item" />' + 
+                               
+                               '<form id="vcard-avatar" action="./php/avatar-upload.php" method="post" enctype="multipart/form-data">' + 
+                                       generateFileShare() + 
+                               '</form>' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Current") + '</legend>' + 
+                               
+                               '<div class="avatar-container"></div>' + 
+                               
+                               '<a href="#" class="one-button avatar-delete talk-images">' + _e("Delete") + '</a>' + 
+                               '<div class="no-avatar">' + _e("What a pity! You have no profile image defined in your identity card!") + '</div>' + 
+                       '</fieldset>' + 
+                       
+                       '<div class="avatar-wait avatar-info">' + _e("Please wait while your avatar is uploaded...") + '</div>' + 
+                       '<div class="avatar-ok avatar-info">' + _e("Here it is! A new beautiful profile image!") + '</div>' + 
+                       '<div class="avatar-error avatar-info">' + _e("The image file is not supported or has a bad size.") + '</div>' + 
+               '</div>' + 
+               
+               '<div id="lap3" class="one-lap forms">' + 
+                       '<fieldset>' + 
+                               '<legend>' + _e("Address") + '</legend>' + 
+                               
+                               '<label for="USER-ADR-STREET">' + _e("Street") + '</label>' + 
+                               '<input type="text" id="USER-ADR-STREET" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-LOCALITY">' + _e("City") + '</label>' + 
+                               '<input type="text" id="USER-ADR-LOCALITY" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-PCODE">' + _e("Postal code") + '</label>' + 
+                               '<input type="text" id="USER-ADR-PCODE" class="vcard-item" />' + 
+                               
+                               '<label for="USER-ADR-CTRY">' + _e("Country") + '</label>' + 
+                               '<input type="text" id="USER-ADR-CTRY" class="vcard-item" />' + 
+                       '</fieldset>' + 
+                       
+                       '<fieldset>' + 
+                               '<legend>' + _e("Biography") + '</legend>' + 
+                               
+                               '<textarea id="USER-DESC" rows="8" cols="60" class="vcard-item"></textarea>' + 
+                       '</fieldset>' + 
+               '</div>' + 
+               
+               '<div class="infos">' + 
+                       '<p class="infos-title">' + _e("Important notice") + '</p>' + 
+                       
+                       '<p>' + _e("Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to).") + '</p>' + 
+                       '<p>' + _e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '</p>' + 
+                       '<p>' + printf(_e("It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."), JAPPIX_MAX_UPLOAD) + '</p>' + 
+                       '<p><a href="https://me.jappix.com/new" target="_blank">' + _e("Enable my public profile") + ' »</a></p>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish save disabled">' + _e("Save") + '</a>' + 
+               '<a href="#" class="finish cancel">' + _e("Cancel") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('vcard', html);
+       
+       // Associate the events
+       launchVCard();
+       
+       // We get the VCard informations
+       getVCard(getXID(), 'user');
+       
+       return false;
+}
+
+// Closes the vCard popup
+function closeVCard() {
+       // Destroy the popup
+       destroyPopup('vcard');
+       
+       // Create the welcome end popup?
+       if(END_WELCOME)
+               openMe();
+       
+       return false;
+}
+
+// Switches the vCard popup tabs
+function switchVCard(id) {
+       $('#vcard .one-lap').removeClass('lap-active');
+       $('#vcard #lap' + id).addClass('lap-active');
+       $('#vcard .tab a').removeClass('tab-active');
+       $('#vcard .tab a[data-key=' + id + ']').addClass('tab-active');
+       
+       return false;
+}
+
+// Waits for the avatar upload reply
+function waitAvatarUpload() {
+       // Reset the avatar info
+       $('#vcard .avatar-info').hide().stopTime();
+       
+       // Show the wait info
+       $('#vcard .avatar-wait').show();
+}
+
+// Handles the avatar upload reply
+function handleAvatarUpload(responseXML) {
+       // Data selector
+       var dData = $(responseXML).find('jappix');
+       
+       // Not current upload session?
+       if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name=id]').val()))
+               return;
+       
+       // Reset the avatar info
+       $('#vcard .avatar-info').hide().stopTime();
+       
+       // Process the returned data
+       if(!dData.find('error').size()) {
+               // Read the values
+               var aType = dData.find('type').text();
+               var aBinval = dData.find('binval').text();
+               
+               // We remove everything that isn't useful right here
+               $('#vcard .no-avatar').hide();
+               $('#vcard .avatar').remove();
+               
+               // We display the delete button
+               $('#vcard .avatar-delete').show();
+               
+               // We tell the user it's okay
+               $('#vcard .avatar-ok').show();
+               
+               // Timer
+               $('#vcard .avatar-info').oneTime('10s', function() {
+                       $(this).hide();
+               });
+               
+               // We put the base64 values in a hidden input to be sent
+               $('#USER-PHOTO-TYPE').val(aType);
+               $('#USER-PHOTO-BINVAL').val(aBinval);
+               
+               // We display the avatar !
+               $('#vcard .avatar-container').replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
+       }
+       
+       // Any error?
+       else {
+               $('#vcard .avatar-error').show();
+               
+               // Timer
+               $('#vcard .avatar-info').oneTime('10s', function() {
+                       $(this).hide();
+               });
+               
+               logThis('Error while uploading the avatar: ' + dData.find('error').text(), 1);
+       }
+}
+
+// Deletes the encoded avatar of an user
+function deleteAvatar() {
+       // We remove the avatar displayed elements
+       $('#vcard .avatar-info').stopTime();
+       $('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide();
+       $('#vcard .avatar').remove();
+       
+       // We reset the input value
+       $('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val('');
+       
+       // We show the avatar-uploading request
+       $('#vcard .no-avatar').show();
+       
+       return false;
+}
+
+// Creates a special vCard input
+function createInputVCard(id, type) {
+       // Generate the new ID
+       id = 'USER-' + id;
+       
+       // Can append the content
+       if((type == 'user') && !exists('#vcard #' + id))
+               $('#vcard .content').append('<input id="' + id + '" class="vcard-item" type="hidden" />');
+}
+
+// Gets the vCard of a XID
+function getVCard(to, type) {
+       // Generate a special ID
+       var id = genID();
+       
+       // New IQ
+       var iq = new JSJaCIQ();
+       iq.setID(id);
+       iq.setType('get');
+       iq.appendNode('vCard', {'xmlns': NS_VCARD});
+       
+       // Send the IQ to the good user
+       if(type == 'user') {
+               // Show the wait icon
+               $('#vcard .wait').show();
+               
+               // Apply the session ID
+               $('#vcard').attr('data-vcard', id);
+               
+               // Send the IQ
+               con.send(iq, handeUVCard);
+       }
+       
+       else {
+               // Show the wait icon
+               $('#userinfos .wait').show();
+               
+               // Apply the session ID
+               $('#userinfos').attr('data-vcard', id);
+               
+               // Send the IQ
+               iq.setTo(to);
+               con.send(iq, handeBVCard);
+       }
+}
+
+// Handles the current connected user's vCard
+function handeUVCard(iq) {
+       handleVCard(iq, 'user');
+}
+
+// Handles an external buddy vCard
+function handeBVCard(iq) {
+       handleVCard(iq, 'buddy');
+}
+
+// Handles a vCard stanza
+function handleVCard(iq, type) {
+       // Extract the data
+       var iqID = iq.getID();
+       var iqFrom = fullXID(getStanzaFrom(iq));
+       var iqNode = iq.getNode();
+       
+       // Define some paths
+       var path_vCard = '#vcard[data-vcard=' + iqID + ']';
+       var path_userInfos = '#userinfos[data-vcard=' + iqID + ']';
+       
+       // End if the session does not exist
+       if(((type == 'user') && !exists(path_vCard)) || ((type == 'buddy') && !exists(path_userInfos)))
+               return;
+       
+       // We retrieve main values
+       var values_yet = [];
+       
+       $(iqNode).find('vCard').children().each(function() {
+               // Read the current parent node name
+               var tokenname = (this).nodeName.toUpperCase();
+               
+               // Node with a parent
+               if($(this).children().size()) {
+                       $(this).children().each(function() {
+                               // Get the node values
+                               var currentID = tokenname + '-' + (this).nodeName.toUpperCase();
+                               var currentText = $(this).text();
+                               
+                               // Not yet added?
+                               if(!existArrayValue(values_yet, currentID)) {
+                                       // Create an input if it does not exist
+                                       createInputVCard(values_yet, type);
+                                       
+                                       // Userinfos viewer popup
+                                       if((type == 'buddy') && currentText) {
+                                               if(currentID == 'EMAIL-USERID')
+                                                       $(path_userInfos + ' #BUDDY-' + currentID).html('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
+                                               else
+                                                       $(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc());
+                                       }
+                                       
+                                       // Profile editor popup
+                                       else if(type == 'user')
+                                               $(path_vCard + ' #USER-' + currentID).val(currentText);
+                                       
+                                       // Avoid duplicating the value
+                                       values_yet.push(currentID);
+                               }
+                       });
+               }
+               
+               // Node without any parent
+               else {
+                       // Get the node values
+                       var currentText = $(this).text();
+                       
+                       // Not yet added?
+                       if(!existArrayValue(values_yet, tokenname)) {
+                               // Create an input if it does not exist
+                               createInputVCard(tokenname, type);
+                               
+                               // Userinfos viewer popup
+                               if((type == 'buddy') && currentText) {
+                                       // URL modification
+                                       if(tokenname == 'URL') {
+                                               // No http:// or https:// prefix, we should add it
+                                               if(!currentText.match(/^https?:\/\/(.+)/))
+                                                       currentText = 'http://' + currentText;
+                                               
+                                               currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
+                                       }
+                                       
+                                       // Description modification
+                                       else if(tokenname == 'DESC')
+                                               currentText = filterThisMessage(currentText, getBuddyName(iqFrom).htmlEnc(), true);
+                                       
+                                       // Other stuffs
+                                       else
+                                               currentText = currentText.htmlEnc();
+                                       
+                                       $(path_userInfos + ' #BUDDY-' + tokenname).html(currentText);
+                               }
+                               
+                               // Profile editor popup
+                               else if(type == 'user')
+                                       $(path_vCard + ' #USER-' + tokenname).val(currentText);
+                               
+                               // Avoid duplicating the value
+                               values_yet.push(tokenname);
+                       }
+               }
+       });
+       
+       // Update the stored avatar
+       if(type == 'buddy') {
+               // Get the avatar XML
+               var xml = getPersistent('avatar', iqFrom);
+               
+               // If there were no stored avatar previously
+               if($(XMLFromString(xml)).find('type').text() == 'none') {
+                       xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>');
+                       setPersistent('avatar', iqFrom, xml);
+               }
+               
+               // Handle the user avatar
+               handleAvatar(iq);
+       }
+       
+       // The avatar values targets
+       var aBinval, aType, aContainer;
+       
+       if(type == 'user') {
+               aBinval = $('#USER-PHOTO-BINVAL').val();
+               aType = $('#USER-PHOTO-TYPE').val();
+               aContainer = path_vCard + ' .avatar-container';
+       }
+       
+       else {
+               aBinval = $(iqNode).find('BINVAL:first').text();
+               aType = $(iqNode).find('TYPE:first').text();
+               aContainer = path_userInfos + ' .avatar-container';
+       }
+       
+       // We display the avatar if retrieved
+       if(aBinval) {
+               // No type?
+               if(!aType)
+                       aType = 'image/png';
+               
+               if(type == 'user') {
+                       // We move all the things that we don't need in that case
+                       $(path_vCard + ' .no-avatar').hide();
+                       $(path_vCard + ' .avatar-delete').show();
+                       $(path_vCard + ' .avatar').remove();
+               }
+               
+               // We display the avatar we have just received
+               $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
+       }
+       
+       else if(type == 'buddy')
+               $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + './img/others/default-avatar.png' + '" alt="" /></div>');
+       
+       // Do someting depending of the type
+       if(type == 'user') {
+               $(path_vCard + ' .wait').hide();
+               $(path_vCard + ' .finish:first').removeClass('disabled');
+       }
+       
+       else
+               vCardBuddyInfos();
+       
+       logThis('vCard received: ' + iqFrom);
+}
+
+// Sends the vCard of the user
+function sendVCard() {
+       // Initialize the IQ
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var vCard = iq.appendNode('vCard', {'xmlns': NS_VCARD});
+       
+       // We send the identity part of the form
+       $('#vcard .vcard-item').each(function() {
+               var itemID = $(this).attr('id').replace(/^USER-(.+)/, '$1');
+               var itemVal = $(this).val();
+               
+               if(itemVal && itemID) {
+                       if(itemID.indexOf('-') != -1) {
+                               var tagname = explodeThis('-', itemID, 0);
+                               var aNode;
+                               
+                               if(vCard.getElementsByTagName(tagname).length > 0)
+                                       aNode = vCard.getElementsByTagName(tagname).item(0);
+                               else
+                                       aNode = vCard.appendChild(iq.buildNode(tagname, {'xmlns': NS_VCARD}));
+                               
+                               aNode.appendChild(iq.buildNode(explodeThis('-', itemID, 1), {'xmlns': NS_VCARD}, itemVal));
+                       }
+                       
+                       else
+                               vCard.appendChild(iq.buildNode(itemID, {'xmlns': NS_VCARD}, itemVal));
+               }
+       });
+       
+       // Send the IQ
+       con.send(iq);
+       
+       // Send the user nickname & avatar over PEP
+       if(enabledPEP()) {
+               // Read values
+               var user_nick = $('#USER-NICKNAME').val();
+               var photo_bin = $('#USER-PHOTO-BINVAL').val();
+               var photo_type = $('#USER-PHOTO-TYPE').val();
+               var photo_data = Base64.decode(photo_bin) || '';
+               var photo_bytes = photo_data.length || '';
+               var photo_id = hex_sha1(photo_data) || '';
+               
+               // Values array
+               var read = [
+                       user_nick,
+                       photo_bin,
+                       [photo_type, photo_id, photo_bytes]
+               ];
+               
+               // Nodes array
+               var node = [
+                       NS_NICK,
+                       NS_URN_ADATA,
+                       NS_URN_AMETA
+               ];
+               
+               // Generate the XML
+               for(i in read) {
+                       var iq = new JSJaCIQ();
+                       iq.setType('set');
+                       
+                       var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
+                       var publish = pubsub.appendChild(iq.buildNode('publish', {'node': node[i], 'xmlns': NS_PUBSUB}));
+                       
+                       if((i == 0) && read[0]) {
+                               var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+                               
+                               // Nickname element
+                               item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, read[i]));
+                       }
+                       
+                       else if(((i == 1) || (i == 2)) && read[1]) {
+                               var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
+                               
+                               // Apply the SHA-1 hash
+                               if(photo_id)
+                                       item.setAttribute('id', photo_id);
+                               
+                               // Avatar data node
+                               if(i == 1)
+                                       item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, read[i]));
+                               
+                               // Avatar metadata node
+                               else {
+                                       var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA}));
+                                       
+                                       if(read[i]) {
+                                               var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA}));
+                                               
+                                               if(read[i][0])
+                                                       meta_info.setAttribute('type', read[i][0]);
+                                               if(read[i][1])
+                                                       meta_info.setAttribute('id', read[i][1]);
+                                               if(read[i][2])
+                                                       meta_info.setAttribute('bytes', read[i][2]);
+                                       }
+                               }
+                       }
+                       
+                       con.send(iq);
+               }
+       }
+       
+       // Close the vCard stuffs
+       closeVCard();
+       
+       // Get our new avatar
+       getAvatar(getXID(), 'force', 'true', 'forget');
+       
+       logThis('vCard sent.');
+       
+       return false;
+}
+
+// Plugin launcher
+function launchVCard() {
+       // Focus on the first input
+       $(document).oneTime(10, function() {
+               $('#vcard input:first').focus();
+       });
+       
+       // Keyboard events
+       $('#vcard input[type=text]').keyup(function(e) {
+               // Enter pressed: send the vCard
+               if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled'))
+                       return sendVCard();
+       });
+       
+       // Click events
+       $('#vcard .tab a').click(function() {
+               // Yet active?
+               if($(this).hasClass('tab-active'))
+                       return false;
+               
+               // Switch to the good tab
+               var key = parseInt($(this).attr('data-key'));
+               
+               return switchVCard(key);
+       });
+       
+       $('#vcard .avatar-delete').click(function() {
+               return deleteAvatar();
+       });
+       
+       $('#vcard .bottom .finish').click(function() {
+               if($(this).is('.cancel'))
+                       return closeVCard();
+               if($(this).is('.save') && !$(this).hasClass('disabled'))
+                       return sendVCard();
+               
+               return false;
+       });
+       
+       // Avatar upload vars
+       var avatar_options = {
+               dataType:       'xml',
+               beforeSubmit:   waitAvatarUpload,
+               success:        handleAvatarUpload
+       };
+       
+       // Avatar upload form submit event
+       $('#vcard-avatar').submit(function() {
+               if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $('#vcard-avatar input[type=file]').val())
+                       $(this).ajaxSubmit(avatar_options);
+               
+               return false;
+       });
+       
+       // Avatar upload input change event
+       $('#vcard-avatar input[type=file]').change(function() {
+               if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $(this).val())
+                       $('#vcard-avatar').ajaxSubmit(avatar_options);
+               
+               return false;
+       });
+}
diff --git a/jappixmini/jappix/js/welcome.js b/jappixmini/jappix/js/welcome.js
new file mode 100644 (file)
index 0000000..4faf5bd
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+
+Jappix - An open social platform
+These are the welcome tool functions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+// Opens the welcome tools
+function openWelcome() {       
+       // Share message
+       var share_msg = printf(_e("Using Jappix, an open social platform. I am %s!"), getXID());
+       
+       // Popup HTML content
+       var html = 
+       '<div class="top">' + _e("Welcome!") + '</div>' + 
+       
+       '<div class="tab">' + 
+               '<a href="#" class="tab-active" data-step="1">' + _e("Options") + '</a>' + 
+               '<a href="#" class="tab-missing" data-step="2">' + _e("Friends") + '</a>' + 
+               '<a href="#" class="tab-missing" data-step="3">' + _e("Share") + '</a>' + 
+       '</div>' + 
+       
+       '<div class="content">' + 
+               '<div class="lap-active one-lap welcome1">' + 
+                       '<div class="infos">' + 
+                               '<p class="infos-title">' + _e("Welcome on Jappix, your own social cloud!") + '</p>' + 
+                               '<p>' + _e("Before you start using it, you will have to change some settings, search for friends and complete your profile.") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<a href="#" class="box enabled" title="' + _e("Click to disable") + '">' + 
+                               '<span class="option">' + _e("Sounds") + '</span>' + 
+                               '<span class="description">' + _e("Enable notification sounds") + '</span>' + 
+                               '<span class="image sound talk-images"></span>' + 
+                               '<span class="tick talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a href="#" class="box enabled pep-hidable" title="' + _e("Click to disable") + '">' + 
+                               '<span class="option">' + _e("Geolocation") + '</span>' + 
+                               '<span class="description">' + _e("Share your position on the globe") + '</span>' + 
+                               '<span class="image geolocation talk-images"></span>' + 
+                               '<span class="tick talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a href="#" class="box xmpplinks-hidable" title="' + _e("Click to enable") + '">' + 
+                               '<span class="option">' + _e("XMPP links") + '</span>' + 
+                               '<span class="description">' + _e("Open XMPP links with Jappix") + '</span>' + 
+                               '<span class="image xmpp talk-images"></span>' + 
+                               '<span class="tick talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a href="#" class="box enabled archives-hidable pref" title="' + _e("Click to enable") + '">' + 
+                               '<span class="option">' + _e("Message archiving") + '</span>' + 
+                               '<span class="description">' + _e("Store a history of your chats") + '</span>' + 
+                               '<span class="image archives talk-images"></span>' + 
+                               '<span class="tick talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a href="#" class="box" title="' + _e("Click to enable") + '">' + 
+                               '<span class="option">' + _e("Offline friends") + '</span>' + 
+                               '<span class="description">' + _e("Don\'t hide offline friends") + '</span>' + 
+                               '<span class="image offline talk-images"></span>' + 
+                               '<span class="tick talk-images"></span>' + 
+                       '</a>' + 
+               '</div>' + 
+               
+               '<div class="one-lap welcome2">' + 
+                       '<div class="infos">' + 
+                               '<p class="infos-title">' + _e("Friends") + '</p>' + 
+                               '<p>' + _e("Use this tool to find your friends on the server you are using right now, or add them later.") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<div class="results welcome-results"></div>' + 
+               '</div>' + 
+               
+               '<div class="one-lap welcome3">' + 
+                       '<div class="infos">' + 
+                               '<p class="infos-title">' + _e("Share") + '</p>' + 
+                               '<p>' + _e("Great work! Now, you can share Jappix with your friends!") + '</p>' + 
+                               '<p>' + _e("When you will press the save button, the profile editor will be opened. Happy socializing!") + '</p>' + 
+                       '</div>' + 
+                       
+                       '<a class="box share first" href="http://www.facebook.com/sharer/sharer.php?u=' + encodeQuotes(generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + 
+                               '<span class="logo facebook welcome-images"></span>' + 
+                               '<span class="name">Facebook</span>' + 
+                               '<span class="description">' + printf(_e("Share Jappix on %s"), 'Facebook') + '</span>' + 
+                               '<span class="go talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a class="box share" href="http://twitter.com/intent/tweet?text=' + encodeQuotes(share_msg) + '&amp;url=' + encodeQuotes(generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + 
+                               '<span class="logo twitter welcome-images"></span>' + 
+                               '<span class="name">Twitter</span>' + 
+                               '<span class="description">' + printf(_e("Share Jappix on %s"), 'Twitter') + '</span>' + 
+                               '<span class="go talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a class="box share" href="http://www.google.com/buzz/post?message=' + encodeQuotes(share_msg) + '&amp;url=' + encodeQuotes(generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + 
+                               '<span class="logo buzz welcome-images"></span>' + 
+                               '<span class="name">Google Buzz</span>' + 
+                               '<span class="description">' + printf(_e("Share Jappix on %s"), 'Google Buzz') + '</span>' + 
+                               '<span class="go talk-images"></span>' + 
+                       '</a>' + 
+                       
+                       '<a class="box share" href="http://identi.ca/index.php?action=newnotice&amp;status_textarea=' + encodeQuotes(share_msg) + ' ' + encodeQuotes(generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + 
+                               '<span class="logo identica welcome-images"></span>' + 
+                               '<span class="name">Identi.ca</span>' + 
+                               '<span class="description">' + printf(_e("Share Jappix on %s"), 'Identi.ca') + '</span>' + 
+                               '<span class="go talk-images"></span>' + 
+                       '</a>' + 
+               '</div>' + 
+       '</div>' + 
+       
+       '<div class="bottom">' + 
+               '<div class="wait wait-medium"></div>' + 
+               
+               '<a href="#" class="finish next">' + _e("Next") + ' »</a>' + 
+               '<a href="#" class="finish save">' + _e("Save") + '</a>' + 
+       '</div>';
+       
+       // Create the popup
+       createPopup('welcome', html);
+       
+       // Apply the features
+       applyFeatures('welcome');
+       
+       // Associate the events
+       launchWelcome();
+       
+       logThis('Welcome assistant opened.');
+}
+
+// Closes the welcome tools
+function closeWelcome() {
+       // Destroy the popup
+       destroyPopup('welcome');
+       
+       return false;
+}
+
+// Switches the welcome tabs
+function switchWelcome(id) {
+       // Path to
+       var welcome = '#welcome ';
+       var content = welcome + '.content .';
+       var tab = welcome + '.tab ';
+       var wait = $(welcome + '.wait');
+       
+       $(content + 'one-lap').hide();
+       $(content + 'welcome' + id).show();
+       $(tab + 'a').removeClass('tab-active');
+       $(tab + 'a[data-step=' + id + ']').addClass('tab-active').removeClass('tab-missing');
+       
+       // Update the "save" button if all is okay
+       if(!exists(tab + '.tab-missing')) {
+               var finish = welcome + '.finish.';
+               $(finish + 'save').show();
+               $(finish + 'next').hide();
+       }
+       
+       // If this is ID 2: vJUD search
+       if(id == 2) {
+               wait.show();
+               dataForm(HOST_VJUD, 'search', '', '', 'welcome');
+       }
+       
+       else
+               wait.hide();
+       
+       return false;
+}
+
+// Sends the welcome options
+function sendWelcome(array) {
+       // Sends the options
+       var iq = new JSJaCIQ();
+       iq.setType('set');
+       
+       var query = iq.setQuery(NS_PRIVATE);
+       var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
+       
+       // Value array
+       var tags = new Array('sounds', 'geolocation', '', '', 'roster-showall');
+       
+       // Build the XML with the array
+       for(i in array) {
+               var value = array[i];
+               var tag = tags[i];
+               
+               if((i != 2) && (i != 3) && tag && value) {
+                       storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value));
+                       setDB('options', tag, value);
+               }
+       }
+       
+       con.send(iq);
+       
+       // If geolocation is enabled
+       if(array[1] == '1')
+               geolocate();
+}
+
+// Saves the welcome options
+var END_WELCOME = false;
+
+function saveWelcome() {
+       // Get the new options
+       var array = new Array();
+       
+       $('#welcome a.box').each(function() {
+               var current = '0';
+               
+               if($(this).hasClass('enabled'))
+                       current = '1';
+               
+               array.push(current);
+       });
+       
+       // If XMPP links is enabled
+       if(array[2] == '1')
+               xmppLinksHandler();
+       
+       // If offline buddies showing is enabled
+       if(array[4] == '1')
+               showAllBuddies('welcome');
+       
+       // If archiving is supported by the server
+       if(enabledArchives('pref')) {
+               var aEnabled = false;
+               
+               // If archiving is enabled
+               if(array[3] == '1')
+                       aEnabled = true;
+               
+               // Send the archives configuration
+               configArchives(aEnabled);
+       }
+       
+       // Send the new options
+       sendWelcome(array);
+       
+       // Close the welcome tool
+       closeWelcome();
+       
+       // Open the profile editor
+       openVCard();
+       
+       END_WELCOME = true;
+       
+       return false;
+}
+
+// Goes to the next welcome step
+function nextWelcome() {
+       // Check the next step to go to
+       var next = 1;
+       var missing = '#welcome .tab a.tab-missing';
+       
+       if(exists(missing))
+               next = parseInt($(missing + ':first').attr('data-step'));
+       
+       // Switch to the next step
+       switchWelcome(next);
+       
+       return false;
+}
+
+// Plugin launcher
+function launchWelcome() {
+       // Click events
+       $('#welcome .tab a').click(function() {
+               // Switch to the good tab
+               var key = parseInt($(this).attr('data-step'));
+               
+               return switchWelcome(key);
+       });
+       
+       $('#welcome a.box:not(.share)').click(function() {
+               if($(this).hasClass('enabled'))
+                       $(this).removeClass('enabled').attr('title', _e("Click to enable"));
+               else
+                       $(this).addClass('enabled').attr('title', _e("Click to disable"));
+               
+               return false;
+       });
+       
+       $('#welcome .bottom .finish').click(function() {
+               if($(this).is('.next'))
+                       return nextWelcome();
+               if($(this).is('.save'))
+                       return saveWelcome();
+               
+               return false;
+       });
+}
diff --git a/jappixmini/jappix/js/xmpplinks.js b/jappixmini/jappix/js/xmpplinks.js
new file mode 100644 (file)
index 0000000..a75ad55
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+
+Jappix - An open social platform
+These are the XMPP links handling JS scripts for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 08/05/11
+
+*/
+
+// Does an action with the provided XMPP link
+function xmppLink(link) {
+       /* REF: http://xmpp.org/registrar/querytypes.html */
+       
+       // Remove the "xmpp:" string
+       link = explodeThis(':', link, 1);
+       
+       // The XMPP URI has no "?"
+       if(link.indexOf('?') == -1)
+               checkChatCreate(link, 'chat');
+       
+       // Parse the URI
+       else {
+               var xid = explodeThis('?', link, 0);
+               var action = explodeThis('?', link, 1);
+               
+               switch(action) {
+                       // Groupchat
+                       case 'join':
+                               checkChatCreate(xid, 'groupchat');
+                               
+                               break;
+                       
+                       // Profile
+                       case 'vcard':
+                               openUserInfos(xid);
+                               
+                               break;
+                       
+                       // Subscription
+                       case 'subscribe':
+                               addThisContact(xid);
+                               
+                               break;
+                       
+                       // Unsubscription
+                       case 'unsubscribe':
+                               sendRoster(xid, 'remove');
+                               
+                               break;
+                       
+                       // Private chat
+                       default:
+                               checkChatCreate(xid, 'chat');
+                               
+                               break;
+               }
+       }
+       
+       return false;
+}
+
+// Gets the links vars (get parameters in URL)
+var LINK_VARS = (function() {
+       var vars = [], hash;
+       var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+       
+       for(var i = 0; i < hashes.length; i++) {
+               var hash = hashes[i].split('=');
+               vars.push(hash[0]);
+               vars[hash[0]] = decodeURIComponent(hash[1]);
+       }
+       
+       return vars;
+})();
diff --git a/jappixmini/jappix/lang/ar/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/ar/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..0f0ec43
Binary files /dev/null and b/jappixmini/jappix/lang/ar/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/ar/LC_MESSAGES/main.po b/jappixmini/jappix/lang/ar/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..c8cc999
--- /dev/null
@@ -0,0 +1,1870 @@
+# Arabic translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "الجافا سكريبت في متصفحك مفقود، لن تتمكن من بدأ Jappix! يرجى إصلاحه."
+
+msgid "An open social network"
+msgstr "شبكة إجتماعية مفتوحة."
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix قد إتقطع بسبب مشكلة في الشبكة، مشكلة أو دخول سيء (تأكد أنك أدخلت المعلومات بشكل صحيح)، نأسف على الإزعاج."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "هذا العنصر من القائمة على هذا الخادم لا يمكن الوصول إليه."
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "لقد تم تغيير رقمك السري، بإمكانك الآن إستخدام حسابك مع المعلومات الجديدة."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "لقد تم حذف حسابك XMPP, وداعًا!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "لقد تم تسجيل خروجك من حسابك XMPP, يومًا طيبًا لك!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "الغرفة التي تحاول الدخول عليها غير متوفرة. قم بإنشاؤها!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "لقد تم حذف غرفة الدردشة، الآن بإمكان شخص آخر إنشاؤها."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "المستخدم الذي تحاول الوصول إليه غير متواجد في الغرفة."
+
+msgid "Please enter the group chat address to join."
+msgstr "يرجى إدخال عنوان مجموعة الدردشة للدخول."
+
+msgid "Please enter your nickname to join %s."
+msgstr "يرجى إدخال إسمك المستعار للدخول %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "هذه الغرفة (%s) .محميّة بكلمة مرور"
+
+msgid "Your browser is out of date!"
+msgstr "متصفحك قديم و عديم الصلاحية"
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr "دخول"
+
+msgid "Register"
+msgstr "تسجيل"
+
+msgid "Here we go!"
+msgstr "هنا ننطلق!"
+
+msgid "Server"
+msgstr "خادم"
+
+msgid "Password"
+msgstr "كلمة سر"
+
+msgid "Remember me"
+msgstr "تذكرني"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "هذه الخاصيّة معطلّة، لن تتمكن من إستخدامها!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "بسبب مشكلة في الشبكة، أصبحت غير متصل. ماذا تريد أن تفعل الآن؟"
+
+msgid "Reconnect"
+msgstr "إعادة إتصال"
+
+msgid "Messages"
+msgstr "رسائل"
+
+msgid "Profile"
+msgstr "ملف شخصي"
+
+msgid "Options"
+msgstr "خيّارات"
+
+msgid "Disconnect"
+msgstr "غير متصل"
+
+msgid "Filter"
+msgstr "مرشح"
+
+msgid "Add a friend"
+msgstr "أضف صديق."
+
+msgid "Your groupchats"
+msgstr "غرفة الدردشة الخاصة بك"
+
+msgid "Manage your favorite groupchats"
+msgstr "تحكم بغرف الدردشة المفضلة لديك"
+
+msgid "More stuff"
+msgstr "خيارات أكثر"
+
+msgid "Show all friends"
+msgstr "أعرض جميع الأصدقاء"
+
+msgid "Only show connected friends"
+msgstr "أعرض فقط الأصدقاء المتصلين"
+
+msgid "Message archives"
+msgstr "أرشفة الرسائل"
+
+msgid "Date"
+msgstr "التاريخ"
+
+msgid "Please select a friend to view the chat history."
+msgstr ""
+
+msgid "Nothing found for: %s"
+msgstr ""
+
+msgid "A short message?"
+msgstr "رسالة قصيرة؟"
+
+msgid "How are you?"
+msgstr "كيف حالك؟"
+
+msgid "What are you doing?"
+msgstr "ماذا تفعل؟"
+
+msgid "Join a chat"
+msgstr "دخول الدردشة"
+
+msgid "Status"
+msgstr "حالة"
+
+msgid "Available"
+msgstr "متاح"
+
+msgid "Talkative"
+msgstr "ثرثرة"
+
+msgid "Away"
+msgstr "بالخارج"
+
+msgid "Not available"
+msgstr "غير متصل"
+
+msgid "Busy"
+msgstr "مشغول"
+
+msgid "Mood"
+msgstr "مزاجي"
+
+msgid "None"
+msgstr "لا شيء"
+
+msgid "Crazy"
+msgstr "مجنون"
+
+msgid "Excited"
+msgstr "متحمس"
+
+msgid "Playful"
+msgstr "لعوب"
+
+msgid "Happy"
+msgstr "سعيد"
+
+msgid "Shocked"
+msgstr "مصدوم"
+
+msgid "Hot"
+msgstr "حر!"
+
+msgid "Sad"
+msgstr "حزين"
+
+msgid "Amorous"
+msgstr "مغرم"
+
+msgid "Confident"
+msgstr "واثق"
+
+msgid "Activity"
+msgstr "نشيط"
+
+msgid "Chores"
+msgstr "أعمال منزلية"
+
+msgid "Drinking"
+msgstr "يشرب"
+
+msgid "Eating"
+msgstr "يأكل"
+
+msgid "Exercising"
+msgstr "يمارس التمارين"
+
+msgid "Grooming"
+msgstr "تبرج"
+
+msgid "Appointment"
+msgstr "تجهيز"
+
+msgid "Inactive"
+msgstr "غير نشط"
+
+msgid "Relaxing"
+msgstr "مسترخي"
+
+msgid "Talking"
+msgstr "يتحدث"
+
+msgid "Traveling"
+msgstr "مسافر"
+
+msgid "Working"
+msgstr "يعمل"
+
+msgid "View profile"
+msgstr "مشاهدة الملف الشخصي"
+
+msgid "Repeat this notice"
+msgstr "كرّر هذه الملاحظة"
+
+msgid "Remove this notice"
+msgstr "أحذف هذه الملاحظة"
+
+msgid "Your profile"
+msgstr "ملفك الشخصي"
+
+msgid "Identity"
+msgstr "الهوية"
+
+msgid "Profile image"
+msgstr "صورة الملف الشخصي"
+
+msgid "Others"
+msgstr "آخرين"
+
+msgid "Personal"
+msgstr "شخصي"
+
+msgid "Complete name"
+msgstr "الإسم كامل"
+
+msgid "Nickname"
+msgstr "الإسم المستعار"
+
+msgid "First name"
+msgstr "الإسم الأول"
+
+msgid "Last name"
+msgstr "الإسم الأخير"
+
+msgid "Date of birth"
+msgstr "تاريخ عيد الميلاد"
+
+msgid "Contact"
+msgstr "إتصل"
+
+msgid "E-mail"
+msgstr "البريد الإلكتروني"
+
+msgid "Phone"
+msgstr "الهاتف"
+
+msgid "Website"
+msgstr "الموقع الشخصي"
+
+msgid "Current"
+msgstr "الحالي"
+
+msgid "Delete"
+msgstr "حذف"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "كم مثير للشفقة! لا توجد صورة للملف الشخصي في هويتك!"
+
+msgid "Address"
+msgstr "العنوان"
+
+msgid "Street"
+msgstr "الشارع"
+
+msgid "City"
+msgstr "المدينة"
+
+msgid "Postal code"
+msgstr "الرمز البريدي"
+
+msgid "Country"
+msgstr "الدولة"
+
+msgid "Biography"
+msgstr "نبذة شخصية"
+
+msgid "Important notice"
+msgstr "ملاحظة هامة"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "كن حذرًا عند وضع معلوماتك في ملفك الشخصي، بإمكان الجميع الوصول إليها (حتى الأشخاص الذين لا تود أن يصلون إليها)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "لا يوجد شي خاص على XMPP; هذه واحدة من الأمور، ملفك الشخصي عام (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "إحفظ"
+
+msgid "Cancel"
+msgstr "إلغاء"
+
+msgid "Edit options"
+msgstr "تحرير الخيارات"
+
+msgid "Channel"
+msgstr "القناة"
+
+msgid "Commands"
+msgstr ""
+
+msgid "Sounds"
+msgstr "الأصوات"
+
+msgid "Privacy"
+msgstr "الخصوصية"
+
+msgid "Message archiving"
+msgstr "أرشفة الرسالة"
+
+msgid "Store a history of your chats"
+msgstr "خزن رسائل الدردشة"
+
+msgid "Geolocation"
+msgstr "تحديد الموقع الجغرافي"
+
+msgid "Empty"
+msgstr "خالي"
+
+msgid "Empty channel"
+msgstr "قناة خالية"
+
+msgid "Persistent"
+msgstr "مستمر"
+
+msgid "Maximum notices"
+msgstr "الحد الأقصى للملاحظات"
+
+msgid "Account"
+msgstr "الحساب"
+
+msgid "Change password"
+msgstr "تغيير كلمة السر"
+
+msgid "Delete account"
+msgstr "حذف الحساب"
+
+msgid "Old"
+msgstr "العمر"
+
+msgid "New (2 times)"
+msgstr "جديد (عنصرين)"
+
+msgid "Continue"
+msgstr "إستمرار"
+
+msgid "To"
+msgstr "إلى"
+
+msgid "Close"
+msgstr "أغلق"
+
+msgid "unknown"
+msgstr "غير معروف"
+
+msgid "Unavailable"
+msgstr "غير متاح"
+
+msgid "is now"
+msgstr "الآن"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "المرجو الانتضار ، يتم رفع صورتك"
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "إنها هنا! صورة ملف شخصي جديدة."
+
+msgid "The image file is not supported or has a bad size."
+msgstr "ملف الصورة لا يدعم أو الحجم لا يتناسب."
+
+msgid "Reply"
+msgstr "الرد"
+
+msgid "Error"
+msgstr "خطأ"
+
+msgid "Click here to solve the error"
+msgstr "انقر هنا لحل المشكل"
+
+msgid "You"
+msgstr "أنت"
+
+msgid "Remove"
+msgstr "حذف"
+
+msgid "Rename"
+msgstr "إعادة الإسم"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "مرحبا، أنا %s، أرغب بإضافتك كصديق لدي."
+
+msgid "Smiley insertion"
+msgstr "إضافة رمز"
+
+msgid "Change style"
+msgstr "التنسيق"
+
+msgid "Text in bold"
+msgstr "نص عريض"
+
+msgid "Text in italic"
+msgstr "نص مائل"
+
+msgid "Underlined text"
+msgstr "نص أسفله خط"
+
+msgid "Save chat"
+msgstr "حفظ الدردشة"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "إضغط على الوصلة التالية للحصول على سجل الدردشة وإنتظر. ومن ثم إضغط مجددًا للحصول على الملف."
+
+msgid "This chat is empty!"
+msgstr "هذه دردشة خالية!"
+
+msgid "Generate file!"
+msgstr "إنشاء ملف!"
+
+msgid "Download file!"
+msgstr "تحميل الملف"
+
+msgid "Clean current chat"
+msgstr "مسح الدردشة الحالية"
+
+msgid "View chat history"
+msgstr ""
+
+msgid "Show user profile"
+msgstr "إظهار ملف العضو الشخصي"
+
+msgid "Add this contact to your friends"
+msgstr "قم بإضافة هذا الحساب إلى أصدقائك"
+
+msgid "Add this groupchat to your favorites"
+msgstr "قم بإضافة مجموعة الدردشة هذه إلى المفضلة"
+
+msgid "All tabs"
+msgstr "جميع التبويب"
+
+msgid "Close this tab"
+msgstr "أغلق هذا التبويب"
+
+msgid "no subject defined for this room."
+msgstr "لا يوجد عنوان إلى هذه الغرفة"
+
+msgid "Administration panel for this room"
+msgstr "لوحة التحكم إلى هذه الغرفة"
+
+msgid "Moderators"
+msgstr "المدراء"
+
+msgid "Participants"
+msgstr "المشاركون"
+
+msgid "Visitors"
+msgstr "الزوار"
+
+msgid "Manage favorite rooms"
+msgstr "التحكم بالغرف المفضلة"
+
+msgid "Change favorites"
+msgstr "تغيير المفضلة"
+
+msgid "Search a room"
+msgstr "إختر غرفة"
+
+msgid "Select a favorite"
+msgstr "إختر مفضلة"
+
+msgid "Getting the name..."
+msgstr "الحصول على إسم"
+
+msgid "Gateway"
+msgstr "بوابة"
+
+msgid "Name"
+msgstr "الإسم"
+
+msgid "Room"
+msgstr "غرفة"
+
+msgid "Add"
+msgstr "إضافة"
+
+msgid "Edit"
+msgstr "تحرير"
+
+msgid "Search a room on"
+msgstr "يبحث عن غرفة"
+
+msgid "No room found on this server."
+msgstr "لا توجد غرفة على هذا الخادم."
+
+msgid "Service discovery"
+msgstr "استكشاف الخدمة"
+
+msgid "Server to query"
+msgstr "خادم للإستعلام"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr "حسابات"
+
+msgid "Authentications"
+msgstr "مصادقة"
+
+msgid "Automation"
+msgstr "تشغيل آلي"
+
+msgid "Clients"
+msgstr "عملاء"
+
+msgid "Collaboration"
+msgstr "إشتراك"
+
+msgid "Components"
+msgstr "محتويات"
+
+msgid "Rooms"
+msgstr "غرف"
+
+msgid "Directories"
+msgstr ""
+
+msgid "Gateways"
+msgstr ""
+
+msgid "News"
+msgstr ""
+
+msgid "Hierarchy"
+msgstr ""
+
+msgid "Proxies"
+msgstr ""
+
+msgid "Publication/Subscription"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Service offline or broken"
+msgstr ""
+
+msgid "Your inbox"
+msgstr "بريدك الوارد"
+
+msgid "Available actions"
+msgstr ""
+
+msgid "Clean"
+msgstr ""
+
+msgid "New"
+msgstr "جديد"
+
+msgid "Received"
+msgstr ""
+
+msgid "Subject"
+msgstr "موضوع"
+
+msgid "Content"
+msgstr "محتوى"
+
+msgid "Send message"
+msgstr "أرسل رسالة"
+
+msgid "Your inbox is empty."
+msgstr "بريدك الوارد فارغ"
+
+msgid "MUC administration"
+msgstr ""
+
+msgid "You administrate this room"
+msgstr "أنت تدير هذه الغرفة"
+
+msgid "Enter new subject"
+msgstr "قم بادخال موضوع جديد"
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Authorizations"
+msgstr ""
+
+msgid "Member list"
+msgstr ""
+
+msgid "Owner list"
+msgstr ""
+
+msgid "Administrator list"
+msgstr ""
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr ""
+
+msgid "Yes, let's do it!"
+msgstr ""
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "صديقك يعير اهتماما للمحادثة"
+
+msgid "Your friend is writing a message..."
+msgstr ""
+
+msgid "Your friend stopped writing a message."
+msgstr ""
+
+msgid "Your friend is doing something else."
+msgstr ""
+
+msgid "Your friend closed the chat."
+msgstr ""
+
+msgid "Requesting this service..."
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "joined the chat room"
+msgstr ""
+
+msgid "left the chat room"
+msgstr ""
+
+msgid "no status"
+msgstr ""
+
+msgid "has been kicked"
+msgstr ""
+
+msgid "has been banned"
+msgstr ""
+
+msgid "no reason"
+msgstr ""
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr ""
+
+msgid "Welcome on %1s, “%2s”."
+msgstr ""
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Resource"
+msgstr ""
+
+msgid "Priority"
+msgstr ""
+
+msgid "Low"
+msgstr ""
+
+msgid "Medium"
+msgstr ""
+
+msgid "High"
+msgstr ""
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr ""
+
+msgid "Share this link with your friends:"
+msgstr ""
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr ""
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr ""
+
+msgid "Manager"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Encrypted"
+msgstr ""
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr ""
+
+msgid "What's up with you?"
+msgstr ""
+
+msgid "Fetching the social channel..."
+msgstr ""
+
+msgid "You are synchronized with your network."
+msgstr ""
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr ""
+
+msgid "Media viewer"
+msgstr ""
+
+msgid "Browse"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Join"
+msgstr ""
+
+msgid "Automatic"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "No result!"
+msgstr ""
+
+msgid "No notifications."
+msgstr ""
+
+msgid "would like to add you as a friend."
+msgstr ""
+
+msgid "would like you to join this chatroom:"
+msgstr ""
+
+msgid "Do you accept?"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "would like to get authorization."
+msgstr ""
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Client"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "Local time"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "User profile"
+msgstr ""
+
+msgid "See his/her position on the globe"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "anonymous mode"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Unclassified"
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Ask for authorization"
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Prohibit"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Groupchat"
+msgstr ""
+
+msgid "Jappix Mobile"
+msgstr ""
+
+msgid "Desktop"
+msgstr ""
+
+msgid "Mobile"
+msgstr ""
+
+msgid "Please wait..."
+msgstr ""
+
+msgid "Please enable JavaScript"
+msgstr ""
+
+msgid "Your channel"
+msgstr ""
+
+msgid "Channel of"
+msgstr ""
+
+msgid "More notices..."
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Send"
+msgstr ""
+
+msgid "Unattach the file"
+msgstr ""
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr ""
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr ""
+
+msgid "Internal server error, try later"
+msgstr ""
+
+msgid "Your form has been sent."
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "XMPP links"
+msgstr ""
+
+msgid "Open XMPP links with Jappix"
+msgstr ""
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr ""
+
+msgid "Friends"
+msgstr ""
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr ""
+
+msgid "Don't hide offline friends"
+msgstr ""
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr ""
+
+msgid "Unknown country"
+msgstr ""
+
+msgid "Click to enable"
+msgstr ""
+
+msgid "Click to disable"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Jappix installation"
+msgstr ""
+
+msgid "Welcome to the Jappix installation!"
+msgstr ""
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr "مرحباً"
+
+msgid "Storage configuration"
+msgstr ""
+
+msgid "Administrator account"
+msgstr "حساب المدير"
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr ""
+
+msgid "Services installation"
+msgstr ""
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr ""
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service name"
+msgstr ""
+
+msgid "Service description"
+msgstr ""
+
+msgid "Connection"
+msgstr ""
+
+msgid "Lock the host"
+msgstr ""
+
+msgid "Anonymous mode"
+msgstr ""
+
+msgid "Registration allowed"
+msgstr ""
+
+msgid "Use a proxy"
+msgstr ""
+
+msgid "Encryption"
+msgstr ""
+
+msgid "HTTPS storage"
+msgstr ""
+
+msgid "Force HTTPS"
+msgstr ""
+
+msgid "Compression"
+msgstr ""
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr ""
+
+msgid "Groupchat host"
+msgstr ""
+
+msgid "Anonymous host"
+msgstr ""
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Finish"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr ""
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Hosts"
+msgstr ""
+
+msgid "Design"
+msgstr ""
+
+msgid "Repeat"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Horizontal"
+msgstr ""
+
+msgid "Vertical"
+msgstr ""
+
+msgid "Center"
+msgstr ""
+
+msgid "Left"
+msgstr ""
+
+msgid "Right"
+msgstr ""
+
+msgid "Top"
+msgstr ""
+
+msgid "Bottom"
+msgstr ""
+
+msgid "Adapt"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "You have been logged out. Goodbye!"
+msgstr ""
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr ""
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr ""
+
+msgid "Backgrounds"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr ""
+
+msgid "Notice"
+msgstr ""
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr ""
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr ""
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr ""
+
+msgid "Update in progress"
+msgstr ""
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr ""
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr ""
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr ""
+
+msgid "Daily"
+msgstr ""
+
+msgid "Weekly"
+msgstr ""
+
+msgid "Monthly"
+msgstr ""
+
+msgid "Yearly"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Clean everything"
+msgstr ""
+
+msgid "Purge cache"
+msgstr ""
+
+msgid "Purge logs"
+msgstr ""
+
+msgid "Purge updates"
+msgstr ""
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Artist"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "The folder is empty."
+msgstr ""
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr ""
+
+msgid "The chosen users have been removed."
+msgstr ""
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "%s days ago"
+msgstr ""
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr ""
+
+msgid "Uncheck all"
+msgstr ""
+
+msgid "Choose"
+msgstr ""
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/bg/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/bg/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..36a4231
Binary files /dev/null and b/jappixmini/jappix/lang/bg/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/bg/LC_MESSAGES/main.po b/jappixmini/jappix/lang/bg/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..5d7e06d
--- /dev/null
@@ -0,0 +1,1870 @@
+# Bulgarian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript на вашия браузър липсва или не е включен, поради което няма да можете да заредите и стартирате Jappix! Моля, поправете/променете това."
+
+msgid "An open social network"
+msgstr "отворена социална мрежа"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix беше прекъснат от мрежови проблем, бъг/буболечка (грешка в кода на програмата) или лошо въведени данни за вход (login) (проверете дали сте въвели правилно потребителските си данни за вход), извинете за неудобството."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Списъкът с елементи на/от този сървър не можа да бъде получен!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Паролата ви е променена, сега можете да се свържете със своята потребителска сметка (акаунт) с новите си потребителски данни за вход."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Вашата потребителска сметка (акаунт) в XMPP е премахната/изтрита, довиждане!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Излязохте от потребителската си сметка (акаунт) в XMPP, приятен ден!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Стаята, в която влязохте, изглежда не съществува. Би трябвало да я създадете сами!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Груповият чат беше премахнат, сега някой друг ще може да го възстанови (пресъздаде)."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Потребителят, с когото се опитвате да се свържете, не е наличен в чат стаята."
+
+msgid "Please enter the group chat address to join."
+msgstr "Моля, въведете адреса на груповия чат, за да се присъедините към него."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Моля, въведете вашия псевдоним (nickname, потребителско име), за да се присъедините към %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Тази стаия (%s) е защитена с парола."
+
+msgid "Your browser is out of date!"
+msgstr "Използвате стар браузър. Моля, обновете го до по-нова стабилна версия чрез Интернет, или го сменете с друг."
+
+msgid "Last %s version is better!"
+msgstr "Последната %s версия е по-добра!"
+
+msgid "Login"
+msgstr "Вход"
+
+msgid "Register"
+msgstr "Регистрация"
+
+msgid "Here we go!"
+msgstr "Хайде!"
+
+msgid "Server"
+msgstr "Сървър"
+
+msgid "Password"
+msgstr "Парола"
+
+msgid "Remember me"
+msgstr "Запомняне"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Този инструмент (тази възможност) е изключена, не можете да я ползвате!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Поради мрежова грешка връзката беше прекъсната. Какво искате да направите сега?"
+
+msgid "Reconnect"
+msgstr "Възвръщане на връзката"
+
+msgid "Messages"
+msgstr "Съобщения"
+
+msgid "Profile"
+msgstr "Профил"
+
+msgid "Options"
+msgstr "Настройки"
+
+msgid "Disconnect"
+msgstr "Изключване/прекъсване на връзката"
+
+msgid "Filter"
+msgstr "Филтър"
+
+msgid "Add a friend"
+msgstr "Добяване на приятел"
+
+msgid "Your groupchats"
+msgstr "Вашите групови чатове"
+
+msgid "Manage your favorite groupchats"
+msgstr "Управление на любимите ви групови чатове"
+
+msgid "More stuff"
+msgstr "Още неща"
+
+msgid "Show all friends"
+msgstr "Показване на всички приятели"
+
+msgid "Only show connected friends"
+msgstr "Показване само на свързаните приятели"
+
+msgid "Message archives"
+msgstr "Архив на съобщенията"
+
+msgid "Date"
+msgstr "Дата"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Моля, изберете приятел, за да видите историята на чата (архива на съобщенията)."
+
+msgid "Nothing found for: %s"
+msgstr "Не е намерено нищо за/относно: %s"
+
+msgid "A short message?"
+msgstr "Кратко съобщение?"
+
+msgid "How are you?"
+msgstr "Как сте?"
+
+msgid "What are you doing?"
+msgstr "Какво правите? Как сте?"
+
+msgid "Join a chat"
+msgstr "Присъединяване към чат"
+
+msgid "Status"
+msgstr "Статус"
+
+msgid "Available"
+msgstr "На разположение (онлайн)"
+
+msgid "Talkative"
+msgstr "Готов за разговори"
+
+msgid "Away"
+msgstr "отсъстващ"
+
+msgid "Not available"
+msgstr "не е на разположение"
+
+msgid "Busy"
+msgstr "зает"
+
+msgid "Mood"
+msgstr "Настроение"
+
+msgid "None"
+msgstr "(без)"
+
+msgid "Crazy"
+msgstr "луд"
+
+msgid "Excited"
+msgstr "развълнуван"
+
+msgid "Playful"
+msgstr "игрив"
+
+msgid "Happy"
+msgstr "щастлив/доволен"
+
+msgid "Shocked"
+msgstr "шокиран"
+
+msgid "Hot"
+msgstr "разгорещен"
+
+msgid "Sad"
+msgstr "тъжен"
+
+msgid "Amorous"
+msgstr "чувствен/страстен/влюбчив"
+
+msgid "Confident"
+msgstr "уверен"
+
+msgid "Activity"
+msgstr "дейност"
+
+msgid "Chores"
+msgstr "задължения"
+
+msgid "Drinking"
+msgstr "пиене"
+
+msgid "Eating"
+msgstr "ядене"
+
+msgid "Exercising"
+msgstr "упражнения"
+
+msgid "Grooming"
+msgstr "в момента се подкрепям/поддържам"
+
+msgid "Appointment"
+msgstr "на среща/служба"
+
+msgid "Inactive"
+msgstr "неактивен"
+
+msgid "Relaxing"
+msgstr "релаксира"
+
+msgid "Talking"
+msgstr "говори (в дискусия)"
+
+msgid "Traveling"
+msgstr "пътува (на път)"
+
+msgid "Working"
+msgstr "работи (на работа)"
+
+msgid "View profile"
+msgstr "Преглед на профила"
+
+msgid "Repeat this notice"
+msgstr "Повторение на съобщението"
+
+msgid "Remove this notice"
+msgstr "Премахване на съобщението"
+
+msgid "Your profile"
+msgstr "Вашият профил"
+
+msgid "Identity"
+msgstr "Идентичност"
+
+msgid "Profile image"
+msgstr "Изображение за профила"
+
+msgid "Others"
+msgstr "Други"
+
+msgid "Personal"
+msgstr "Лични"
+
+msgid "Complete name"
+msgstr "Пълно име"
+
+msgid "Nickname"
+msgstr "Псевдоним (nickname)"
+
+msgid "First name"
+msgstr "Първо име (лично име)"
+
+msgid "Last name"
+msgstr "Последно име (фамилия)"
+
+msgid "Date of birth"
+msgstr "Дата на раждане"
+
+msgid "Contact"
+msgstr "Контакт"
+
+msgid "E-mail"
+msgstr "Имейл (е-поща)"
+
+msgid "Phone"
+msgstr "Телефон"
+
+msgid "Website"
+msgstr "Уебсайт"
+
+msgid "Current"
+msgstr "Настоящ"
+
+msgid "Delete"
+msgstr "Изтриване"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Колко жалко! Вие нямате зададено изображение за профила си в картата си за самоличност!"
+
+msgid "Address"
+msgstr "Адрес"
+
+msgid "Street"
+msgstr "Улица"
+
+msgid "City"
+msgstr "Град"
+
+msgid "Postal code"
+msgstr "Пощенски код"
+
+msgid "Country"
+msgstr "Страна/държава"
+
+msgid "Biography"
+msgstr "Биография"
+
+msgid "Important notice"
+msgstr "Важно съобщение"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Внимавайте каква и колко информация вписвате в профила си, защото е достъпна за всички (дори за хора, които не искате)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Не всичко е конфиденциално/поверително в XMPP; вашият публичен профил (vCard) е едно от тези неща."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "Запазване"
+
+msgid "Cancel"
+msgstr "Отказ"
+
+msgid "Edit options"
+msgstr "Редакция на настройките"
+
+msgid "Channel"
+msgstr "Канал"
+
+msgid "Commands"
+msgstr "Команди"
+
+msgid "Sounds"
+msgstr "Звуци"
+
+msgid "Privacy"
+msgstr "Поверителност"
+
+msgid "Message archiving"
+msgstr "Архивиране на съобщенията"
+
+msgid "Store a history of your chats"
+msgstr "Запазване на история (водене на архив) на вашите чатове"
+
+msgid "Geolocation"
+msgstr "Геолокация"
+
+msgid "Empty"
+msgstr "Празно"
+
+msgid "Empty channel"
+msgstr "Празен канал"
+
+msgid "Persistent"
+msgstr "Натрапчивост/постоянство"
+
+msgid "Maximum notices"
+msgstr "Максимален брой съобщения"
+
+msgid "Account"
+msgstr "Потребителска сметка (акаунт)"
+
+msgid "Change password"
+msgstr "Промяна на паролата"
+
+msgid "Delete account"
+msgstr "Изтриване на потребителската сметка (акаунт)"
+
+msgid "Old"
+msgstr "Стар(и)"
+
+msgid "New (2 times)"
+msgstr "Нов(и) (2 пъти)"
+
+msgid "Continue"
+msgstr "Продължаване"
+
+msgid "To"
+msgstr "Към/за"
+
+msgid "Close"
+msgstr "Затваряне"
+
+msgid "unknown"
+msgstr "непознат"
+
+msgid "Unavailable"
+msgstr "Не е на разположение (офлайн)"
+
+msgid "is now"
+msgstr "е сега"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Моля, изчакайте докато аватарът ви се качва (ъплоудва)..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Ето го! Хубаво ново изображение (аватар) за профила ви!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Файлът от тип изображение не се поддържа или има грешна големина."
+
+msgid "Reply"
+msgstr "Отговор"
+
+msgid "Error"
+msgstr "Грешка"
+
+msgid "Click here to solve the error"
+msgstr "Натиснете тук, за да поправите грешката"
+
+msgid "You"
+msgstr "Ти/Вие"
+
+msgid "Remove"
+msgstr "Премахване"
+
+msgid "Rename"
+msgstr "Преименуване"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Здравей, аз съм %s, бих искал да ви добавя към моя списък с приятели."
+
+msgid "Smiley insertion"
+msgstr "Въвеждане на емотикон(и)"
+
+msgid "Change style"
+msgstr "Промяна на стила"
+
+msgid "Text in bold"
+msgstr "Удебелен текст (bold)"
+
+msgid "Text in italic"
+msgstr "Курсивен текст (italic)"
+
+msgid "Underlined text"
+msgstr "Подчертан текст"
+
+msgid "Save chat"
+msgstr "Запазване на чата"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Натиснете следната връзка (хиперлинк), за да получите историята на чата, след това изчакайте. След това натиснете отново, за да изтеглите файла с историята на чата."
+
+msgid "This chat is empty!"
+msgstr "Чатът е празен!"
+
+msgid "Generate file!"
+msgstr "Генериране на файл!"
+
+msgid "Download file!"
+msgstr "Изтегляне (даунлоуд) на файл!"
+
+msgid "Clean current chat"
+msgstr "Изчистване на настоящия чат"
+
+msgid "View chat history"
+msgstr "Преглед на историята на чата"
+
+msgid "Show user profile"
+msgstr "Показване на потребителския профил"
+
+msgid "Add this contact to your friends"
+msgstr "Добавяне на контакта към списъка с приятели"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Добавяне на груповия чат към твоите любими"
+
+msgid "All tabs"
+msgstr "Всички подпрозорци (табове)"
+
+msgid "Close this tab"
+msgstr "Затваряне на подпрозореца (таба)"
+
+msgid "no subject defined for this room."
+msgstr "Не е дефинирана тема за тази чат стая."
+
+msgid "Administration panel for this room"
+msgstr "Администрационен панел за стаята"
+
+msgid "Moderators"
+msgstr "Модератори"
+
+msgid "Participants"
+msgstr "Участници"
+
+msgid "Visitors"
+msgstr "Посетители"
+
+msgid "Manage favorite rooms"
+msgstr "Управление на любимите стаи"
+
+msgid "Change favorites"
+msgstr "Промяна на любимите"
+
+msgid "Search a room"
+msgstr "Търсене из/в стаята"
+
+msgid "Select a favorite"
+msgstr "Избор на любим(и)"
+
+msgid "Getting the name..."
+msgstr "Прихващане на имена..."
+
+msgid "Gateway"
+msgstr "Врата/вход/път"
+
+msgid "Name"
+msgstr "Име"
+
+msgid "Room"
+msgstr "Стая"
+
+msgid "Add"
+msgstr "Добавяне"
+
+msgid "Edit"
+msgstr "Редактиране"
+
+msgid "Search a room on"
+msgstr "Потърси статия от/в(ъв)"
+
+msgid "No room found on this server."
+msgstr "Не са намерени стаи на този сървър."
+
+msgid "Service discovery"
+msgstr "Откриване на услуги"
+
+msgid "Server to query"
+msgstr "Заявка за сървър"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Съжалявам, но търсенето за обекта не върна никакъв резултат!"
+
+msgid "Accounts"
+msgstr "Потребителски сметки (акаунти)"
+
+msgid "Authentications"
+msgstr "Удостоверения за идентификация"
+
+msgid "Automation"
+msgstr "Автоматизация"
+
+msgid "Clients"
+msgstr "Клиенти"
+
+msgid "Collaboration"
+msgstr "Сътрудничество (колаборация)"
+
+msgid "Components"
+msgstr "Компоненти"
+
+msgid "Rooms"
+msgstr "Стаи"
+
+msgid "Directories"
+msgstr "Директории"
+
+msgid "Gateways"
+msgstr "Пътища/входове"
+
+msgid "News"
+msgstr "Новини"
+
+msgid "Hierarchy"
+msgstr "Йерархия"
+
+msgid "Proxies"
+msgstr "Проксита (сървъри-посредници)"
+
+msgid "Publication/Subscription"
+msgstr "Публикация/Абонамент"
+
+msgid "Storage"
+msgstr "Хранилище"
+
+msgid "Service offline or broken"
+msgstr "Услугата е офлайн (извън линия) или е счупена/повредена"
+
+msgid "Your inbox"
+msgstr "Вашата входяща кутия"
+
+msgid "Available actions"
+msgstr "Действия на разположение"
+
+msgid "Clean"
+msgstr "Изчистване"
+
+msgid "New"
+msgstr "Нов(и)"
+
+msgid "Received"
+msgstr "Получен(и)"
+
+msgid "Subject"
+msgstr "Тема"
+
+msgid "Content"
+msgstr "Съдържание"
+
+msgid "Send message"
+msgstr "Изпращане на съобщението"
+
+msgid "Your inbox is empty."
+msgstr "Входящата ви кутия е празна."
+
+msgid "MUC administration"
+msgstr "Администрация на MUC"
+
+msgid "You administrate this room"
+msgstr "Вие сте администраторът на тази стая"
+
+msgid "Enter new subject"
+msgstr "Въвеждане на това тема"
+
+msgid "Configuration"
+msgstr "Конфигурация"
+
+msgid "Authorizations"
+msgstr "Права и пълномощни"
+
+msgid "Member list"
+msgstr "Списък с участници"
+
+msgid "Owner list"
+msgstr "Списък със собственици"
+
+msgid "Administrator list"
+msgstr "Списък с администратори"
+
+msgid "Outcast list"
+msgstr "Списък с outcast-и"
+
+msgid "Add an input"
+msgstr "Добавяне на входни данни"
+
+msgid "Destroy this MUC"
+msgstr "Унищожаване на този MUC (многопотребителски чат)"
+
+msgid "Yes, let's do it!"
+msgstr "Да, да го направим!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Приятелят ви обръща внимание на дискусията."
+
+msgid "Your friend is writing a message..."
+msgstr "Приятелят ви пише съобщение..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Приятелят ви спря да пише съобщение."
+
+msgid "Your friend is doing something else."
+msgstr "Приятелят ви прави нещо друго."
+
+msgid "Your friend closed the chat."
+msgstr "Приятелят ви затваря чата."
+
+msgid "Requesting this service..."
+msgstr "Заявка на тази услуга..."
+
+msgid "Loading"
+msgstr "Зареждане"
+
+msgid "joined the chat room"
+msgstr "се присъедини към чат стаята"
+
+msgid "left the chat room"
+msgstr "напусна чат стаята"
+
+msgid "no status"
+msgstr "без статус"
+
+msgid "has been kicked"
+msgstr "беше изхвърлен (kick-нат) [от стаята]"
+
+msgid "has been banned"
+msgstr "е баннат"
+
+msgid "no reason"
+msgstr "без причина"
+
+msgid "Communicate with the entire world!"
+msgstr "Комуникирай с целия свят!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Позволява ви да се свързвате с милиони потребители, които използват мрежата XMPP както и ти с Jappix. Присъедини се към общността и остани свободен. Пояснение: XMPP = екс-ем-пи-пи, eXtensible Messaging and Presence Protocol, http://xmpp.org/."
+
+msgid "Hi there!"
+msgstr "Ей, ти там, здравей!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Добре дошли в %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Влезте във вашата вече съществуваща XMPP потребителска сметка (акаунт) или създайте нова свободно и безплатно!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix е проект с отворен код (FLOSS, свободен софтуер) от PostPro, некомерсиална (non-profit) организация, която ни осигурява много помощ."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Влезте във вече наличната си (съществуваща) XMPP потребителска сметка (акаунт). Също така можете да използвате %s, за да се присъедините към групов чат."
+
+msgid "Previous"
+msgstr "Предишни"
+
+msgid "General"
+msgstr "Общи"
+
+msgid "Advanced"
+msgstr "Разширени"
+
+msgid "Resource"
+msgstr "Ресурс"
+
+msgid "Priority"
+msgstr "Приоритет"
+
+msgid "Low"
+msgstr "Нисък"
+
+msgid "Medium"
+msgstr "Среден"
+
+msgid "High"
+msgstr "Висок"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Въведете адреса на груповия чат, към който искате да се присъедините, както и псевдонимът, който искате да използвате. Също така можете да се върнете към %s."
+
+msgid "login page"
+msgstr "страница за вход"
+
+msgid "Share this link with your friends:"
+msgstr "Споделяне на връзката с вашите приятели:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Регистрирайте нова потребителска сметка (акаунт) за XMPP, за да се присъедините към вашите приятели от вашия собствен социален облак. Просто е!"
+
+msgid "Required"
+msgstr "задължително"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Вие се регистрирахте успешно, ето ви вашия личен XMPP адрес:"
+
+msgid "Manager"
+msgstr "Мениджър (адм. управление)"
+
+msgid "Project"
+msgstr "Проект"
+
+msgid "Encrypted"
+msgstr "Криптиран (шифрован) вход"
+
+msgid "Unencrypted"
+msgstr "Некриптиран (нешифрован) вход"
+
+msgid "Where are you?"
+msgstr "Къде сте?"
+
+msgid "What's up with you?"
+msgstr "Как сте?"
+
+msgid "Fetching the social channel..."
+msgstr "Прихващане на социалния канал..."
+
+msgid "You are synchronized with your network."
+msgstr "Синхронизиран сте с мрежата си."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Не можете да изпращате нищо: можете само да получавате известия!"
+
+msgid "Media viewer"
+msgstr "Медиен преглед/разглеждане"
+
+msgid "Browse"
+msgstr "Разглеждане/преглед"
+
+msgid "Command"
+msgstr "Команда"
+
+msgid "Subscribe"
+msgstr "Абонамент"
+
+msgid "Join"
+msgstr "Присъединяване"
+
+msgid "Automatic"
+msgstr "Автоматично"
+
+msgid "Search"
+msgstr "Търсене"
+
+msgid "No result!"
+msgstr "Няма резултат!"
+
+msgid "No notifications."
+msgstr "Няма известия."
+
+msgid "would like to add you as a friend."
+msgstr "желае да ви добави към списъка си с приятели."
+
+msgid "would like you to join this chatroom:"
+msgstr "желае вие да се присъедините към следната чат стая:"
+
+msgid "Do you accept?"
+msgstr "Приемате ли?"
+
+msgid "Yes"
+msgstr "Да/ОК"
+
+msgid "No"
+msgstr "Не"
+
+msgid "would like to get authorization."
+msgstr "желае да получи пълномощно."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Желаете ли да видите списъка с приятели, които %s ви предлага?"
+
+msgid "Submit"
+msgstr "Изпращане"
+
+msgid "Client"
+msgstr "Клиент"
+
+msgid "System"
+msgstr "Система"
+
+msgid "Local time"
+msgstr "Местно време"
+
+msgid "Comments"
+msgstr "Коментари"
+
+msgid "User profile"
+msgstr "Потребителски профил"
+
+msgid "See his/her position on the globe"
+msgstr "Вижте неговата/нейната позиция (местоположение) на глобуса [чрез геолокация]"
+
+msgid "Confirm"
+msgstr "Потвърждаване"
+
+msgid "anonymous mode"
+msgstr "режим инкогнито (в анонимност)"
+
+msgid "Groups"
+msgstr "Групи"
+
+msgid "Unclassified"
+msgstr "Некласифицирани"
+
+msgid "Authorize"
+msgstr "Разрешаване/упълномощаване"
+
+msgid "Ask for authorization"
+msgstr "Питай/-не за разрешение/упълномощение"
+
+msgid "Unblock"
+msgstr "Отблокиране"
+
+msgid "Prohibit"
+msgstr "Забрана"
+
+msgid "Block"
+msgstr "Блокиране"
+
+msgid "Chat"
+msgstr "Чат"
+
+msgid "Groupchat"
+msgstr "Групов чат"
+
+msgid "Jappix Mobile"
+msgstr "мобилна версия на Jappix"
+
+msgid "Desktop"
+msgstr "Desktop (десктоп, настолна версия)"
+
+msgid "Mobile"
+msgstr "Mobile (мобилна версия)"
+
+msgid "Please wait..."
+msgstr "Моля, изчакайте..."
+
+msgid "Please enable JavaScript"
+msgstr "Моля, включете JavaScript"
+
+msgid "Your channel"
+msgstr "Вашия канал"
+
+msgid "Channel of"
+msgstr "Канал на"
+
+msgid "More notices..."
+msgstr "Още известия..."
+
+msgid "Attach a file"
+msgstr "Прикачване на файл"
+
+msgid "Send"
+msgstr "Изпращане"
+
+msgid "Unattach the file"
+msgstr "Премахване на прикачения файл"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Грешка при качването (ъплоудването) на вашия файл: може би е прекалено голям (максимумът е %s) или е от забранен тип файлово разширение!"
+
+msgid "Authorization failed"
+msgstr "Неуспешно потвърждение на потребителските данни"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Регистрацията е неуспешна, моля, изберете друго потребителско име/псевдоним"
+
+msgid "Service unavailable"
+msgstr "Услугата не е на разположение (офлайн, извън линия)"
+
+msgid "Internal server error, try later"
+msgstr "Вътрешна сървърна грешка, пробвайте отново по-късно"
+
+msgid "Your form has been sent."
+msgstr "Формулярът ви беше изпратен."
+
+msgid "Application"
+msgstr "Приложение"
+
+msgid "XMPP links"
+msgstr "XMPP връзки"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Отваряне на XMPP връзки с Jappix"
+
+msgid "changed the subject to:"
+msgstr "промени темата на:"
+
+msgid "Welcome!"
+msgstr "Добре дошли!"
+
+msgid "Friends"
+msgstr "Приятели"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Добре дошли в Jappix, твоят собствен социален облак!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Преди да започнете да го използвате, трябва да промените някои настройки, да потърсите приятели и да попълните профила си."
+
+msgid "Enable notification sounds"
+msgstr "Включване на звуци за известия"
+
+msgid "Share your position on the globe"
+msgstr "Споделяне на позицията (местоположението) ви на глобуса"
+
+msgid "Offline friends"
+msgstr "Приятели извън линия"
+
+msgid "Don't hide offline friends"
+msgstr "Без скриване на прителите извън линия"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Използвайте този помощник/инструмент, за да намерите приятелите си на сървъра, който използвате в момента, или ги добавете по-късно."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Добра работа! Сега можете да споделите Jappix със своите приятели!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Когато натиснете бутона за запазване, ще бъде отворен редакторът на профила. Приятно социализиране!"
+
+msgid "Share Jappix on %s"
+msgstr "Споделяне на Jappix по %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Използвам Jappix, отворена социална платформа. Аз съм %s!"
+
+msgid "Unknown name"
+msgstr "Неизвестно име"
+
+msgid "Unknown country"
+msgstr "Неизвестна страна/държава"
+
+msgid "Click to enable"
+msgstr "Натиснете за включване"
+
+msgid "Click to disable"
+msgstr "Натиснете за изключване"
+
+msgid "Installation"
+msgstr "Инсталация"
+
+msgid "Jappix installation"
+msgstr "Инсталация на Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Добре дошли в инсталацията за/на Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Този помощник/инструмент ще ви помогне бързо да инсталирате Jappix, първата пълноценна онлайн социална платформа, базирана на XMPP, на вашия сървър. Дори не са ви нужни технически познания."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Нека да разгледаме стъпките при/на инсталацията:"
+
+msgid "Welcome"
+msgstr "Здравейте"
+
+msgid "Storage configuration"
+msgstr "Конфигурация на хранилището"
+
+msgid "Administrator account"
+msgstr "Администраторска потребителска сметка (акаунт)"
+
+msgid "Main configuration"
+msgstr "Основна конфигурация"
+
+msgid "Hosts configuration"
+msgstr "Конфигурация на хостовете"
+
+msgid "Services installation"
+msgstr "Инсталация на услуги"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Ако настоящият език не съвпада с вашия (%1s), можете да направите Jappix да говори на %2s, като това ще се запази."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Ако желаете да получите помощ относно инсталацията и конфигурацията на Jappix, можете да използвате цялата наша документация на програмата, която е на разположение от:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Време е да построите вашия собствен социален облак: просто отидете на следващата стъпка!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix съхранява натрапчиви/постоянни данни (като споделени файлове, дневници/архиви на чатовете, вашата музика и собствената си конфигурация) в своята собствена сигурна папка/директория за съхранение."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix трябва да може да вписва данни в тази папка/директория, за да създаде своите поддиректории. Ако това е невъзможно, трябва да настроите правомощията на %1s или да промените собственика на папката на %2s (в зависимост от вашата конфигурация)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "В тази папка/директория може да се записва, можете да продължите!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix ви позволява да управлявате и менажирате вашата конфигурация, да инсталирате нови разширения (плъгини) или да потърсите за обновления на програмата (ъпдейти). Затова трябва да създадете администраторска потребителска сметка (акаунт), за да можете да имате достъп до мениджъра с настройките на Jappix."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Когато Jappix се инсталира, просто натиснете върху хипервръзката към мениджъра с настройките за програмата, намиращ се на домашната страница, за да влезете в него."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Опа, пропуснали сте нещо или двете пароли не съвпадат!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix изисква да му въведете някои стойности, за да функционира правилно. Моля, коригирайте следните входни данни (или останете със стойностите по подразбиране, които вършат работа на повечето хора)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Обърнете внимание на това, че ако не изберете ръчно стойност, която е задължителна, тя автоматично ще бъде попълнена с фабрична стойност по подразбиране."
+
+msgid "User"
+msgstr "Потребител"
+
+msgid "Service"
+msgstr "Услуга"
+
+msgid "Service name"
+msgstr "Наименование на услугата"
+
+msgid "Service description"
+msgstr "Описание на услугата"
+
+msgid "Connection"
+msgstr "Връзка"
+
+msgid "Lock the host"
+msgstr "Заключване на хоста"
+
+msgid "Anonymous mode"
+msgstr "Режим инкогнито (в анонимност)"
+
+msgid "Registration allowed"
+msgstr "Регистрациите са разрешени"
+
+msgid "Use a proxy"
+msgstr "Използване на прокси (сървър-посредник)"
+
+msgid "Encryption"
+msgstr "Криптиране (шифроване)"
+
+msgid "HTTPS storage"
+msgstr "съхранение/складиране с HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Принудително използване на HTTPS"
+
+msgid "Compression"
+msgstr "Компресия"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Тази страница ви помага да настроите хостовете по подразбиране, с които Jappix ще се свързва. Можете да оставите настройките такива, каквито са по подразбиране, и да продължите напред, ако искате да използвате официалните хостове на услуги."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Може би не знаете какво е BOSH сървър? Всъщност, това е вид междинна станция между Jappix клиента и определен XMPP сървър, като тя е нужна поради технически ограничения."
+
+msgid "Main host"
+msgstr "Основен хост"
+
+msgid "Groupchat host"
+msgstr "Хост на групови чатове"
+
+msgid "Anonymous host"
+msgstr "Анонимен хост"
+
+msgid "Directory host"
+msgstr "Хост на директорията"
+
+msgid "BOSH host"
+msgstr "BOSH хост"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Можете да инсталирате допълнителни софтурни продукти на вашия сървър, с които да разширите възможностите на вашата инсталация на Jappix. Някои други могат да бъдат модифицирани поради ограничения заради сигурността, които са сложени по подразбиране."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "За да изпълните това действие е необходимо да имате достъп до shell-а (черупката) на вашия сървър и да бъдете влезли в системата му като root (корен) потребител, т.е. с административни права. Запомнете, че това е незадължително, Jappix ще работи и без тези модули, но някои от неговите възможности може да не са налични за използване поради това."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "След като приключите с инсталацията, Jappix ще генерира/създаде кеш (cache) файловете. Това може да бъде бавен процес, затова просто покачайте, докато приложението не се визуализира, и междувременно не натискайте каквито и да е бутони."
+
+msgid "Thanks for using Jappix!"
+msgstr "Благодарим ви, че използвате Jappix!"
+
+msgid "Next"
+msgstr "Следващ/напред"
+
+msgid "Finish"
+msgstr "Край"
+
+msgid "Check again"
+msgstr "Проверете отново"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Не можете да записвате в тази папка/директория, поставете правилните пълномощни права/свойства на директорията %s."
+
+msgid "%s is installed on your system."
+msgstr "%s е инсталиран на вашата система."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s не е инсталиран/а/о на вашата система, нужно е да инсталирате %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "Максималната големина за качване на PHP е достатъчна (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "Максималната големина за качване на/чрез/с PHP е недостатъчна (%1s), нужно е да я промените към %2s в %3s."
+
+msgid "Jappix manager"
+msgstr "Jappix мениджър"
+
+msgid "Manager access"
+msgstr "Мениджърски достъп"
+
+msgid "Statistics"
+msgstr "Статистики"
+
+msgid "Hosts"
+msgstr "Хостове"
+
+msgid "Design"
+msgstr "Дизайн"
+
+msgid "Repeat"
+msgstr "повтаряне"
+
+msgid "All"
+msgstr "Всички"
+
+msgid "Horizontal"
+msgstr "Хоризонтално"
+
+msgid "Vertical"
+msgstr "Вертикално"
+
+msgid "Center"
+msgstr "Централно"
+
+msgid "Left"
+msgstr "Отляво"
+
+msgid "Right"
+msgstr "Отдясно"
+
+msgid "Top"
+msgstr "горе"
+
+msgid "Bottom"
+msgstr "Долу"
+
+msgid "Adapt"
+msgstr "Адаптивно"
+
+msgid "Color"
+msgstr "Цвят"
+
+msgid "Users"
+msgstr "Потребители"
+
+msgid "Updates"
+msgstr "Обновления"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Това е ограничена зона: само оправомощени потребители могат да управляват този Jappix възел."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Моля, използвайте формуляра надолу, за да влезете в администрационния панел."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "За подобряване на сигурността, сесиите са времево ограничени и когато уеббраузърът ви бъде затворен, вие автоматично ще бъдете изхвърлени от системата."
+
+msgid "Credentials"
+msgstr "Акредитивни пълномощни/права"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Вие излязохте. Довиждане!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Опа, системата не ви разпознава като валиден администратор. Моля, проверете верността на данните си за вход!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Променете конфигурацията на вашия Jappix възел с този инструмент/помощник."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Промяна на XMPP хостовете, които обслужва този Jappix възел, с този инструмент/помощник."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Всички съхранени файлове за/на този Jappix възел могат да бъдат управлявани с този инструмент/помощник: за целта, моля, изберете подпапка и започнете да редактирате съдържанието ѝ!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix може напълно да се промени по вкуса ви: можете да промените неговия дизайн от тук."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Изображението е невалидно, моля, използвайте изображения с файлови формати PNG, GIF или JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Изображението не може да бъде получено, бихте ли пробвали да го изпратите отново?"
+
+msgid "Your image was added to the list!"
+msgstr "Вашето изображение е добавено към списъка!"
+
+msgid "Changes saved!"
+msgstr "Промените са запазени!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Можете да изберете повече от един администратор за този Jappix възел. Също така можете да промените парола чрез този инструмент/помощник."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "С този инструмент/помощник можете да обновите версията на вашия Jappix възел, или да проверите дали е налична нова версия. Информация относно най-новата версия също се показва (на английски)."
+
+msgid "Access statistics"
+msgstr "Достъп до статистиките"
+
+msgid "Share statistics"
+msgstr "Споделяне на статистиките"
+
+msgid "Other statistics"
+msgstr "Други статистики"
+
+msgid "January"
+msgstr "януари"
+
+msgid "February"
+msgstr "февруари"
+
+msgid "March"
+msgstr "март"
+
+msgid "April"
+msgstr "април"
+
+msgid "May"
+msgstr "май"
+
+msgid "June"
+msgstr "юни"
+
+msgid "July"
+msgstr "юли"
+
+msgid "August"
+msgstr "август"
+
+msgid "September"
+msgstr "септември"
+
+msgid "October"
+msgstr "октомври"
+
+msgid "November"
+msgstr "ноември"
+
+msgid "December"
+msgstr "декември"
+
+msgid "Monday"
+msgstr "понеделник"
+
+msgid "Tuesday"
+msgstr "вторник"
+
+msgid "Wednesday"
+msgstr "сряда"
+
+msgid "Thursday"
+msgstr "четвъртък"
+
+msgid "Friday"
+msgstr "петък"
+
+msgid "Saturday"
+msgstr "събота"
+
+msgid "Sunday"
+msgstr "неделя"
+
+msgid "Total"
+msgstr "Общо"
+
+msgid "Cache"
+msgstr "Кеш (cache)"
+
+msgid "Logs"
+msgstr "Дневници (logs)"
+
+msgid "Music"
+msgstr "Музика"
+
+msgid "Backgrounds"
+msgstr "Фонове"
+
+msgid "Share"
+msgstr "Споделяне"
+
+msgid "Background"
+msgstr "Фон"
+
+msgid "Notice"
+msgstr "Бележка"
+
+msgid "Your design preferences have been saved!"
+msgstr "Предпочитанията ви за дизайна са запазени!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Моля, проверете своите входни данни: нещо липсва!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Променете фона на вашия Jappix възел с този инструмент. Можете или да сложите цвят по избор за фон, или да използвате качено изображение за фон. Нека вашата креативност се лее!"
+
+msgid "Use default background"
+msgstr "Използване на фона по подразбиране (фабричния фон)"
+
+msgid "Use your own image"
+msgstr "Използване на ваше изображение"
+
+msgid "Select a background to use and change the display options."
+msgstr "Изберете фона, който ще използвате, и променете настройките за визуализация."
+
+msgid "Use your own color"
+msgstr "Използване на цвят по ваш избор"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Въведете шестнадесетичната (HTML hex) стойност на цвета, който искате да използвате за фон."
+
+msgid "Manage backgrounds"
+msgstr "Управление на фоновете"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Можете да добавите нов фон към списъка с помощта на този инструмент/помощник. Моля, качете валидно изображение."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "С този инструмент/помощник можете да дефинирате съдържанието на бележка (за показване на основната страница на Jappix възела ви), например предупреждение, важно съобщение или реклама."
+
+msgid "Simple notice"
+msgstr "Проста бележка"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Това известие изисква визуализацията само на прост текст, но не е позволена употребата на код в него!"
+
+msgid "Advanced notice"
+msgstr "Разширена бележка"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Можете да промените по вкуса ви бележката чрез вградени (embedded) HTML, CSS и JavaScript, но трябва сами да кодирате (напишете кода) на стила."
+
+msgid "Available updates"
+msgstr "Обновления (ъпдейти) на разположение"
+
+msgid "What's new?"
+msgstr "Какво ново?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Вашите папките/директории хранилища не позволяват запис в тях, моля, приложете правилните правомощия/свойства за папките!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s може да предизвика проблеми на проксито (сървъра-посредник), моля, увеличете стойността %2s до %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Използвате версия на Jappix за разработчици (т.е. не стабилна версия за крайни потребители, а нестабилна версия за разработчици). Можете да обновите Jappix чрез нашето хранилище, като изпълните командата: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Налична е нова версия на Jappix! Проверете какво ново има и пуснете да се инсталира обновлението (ъпдейта)!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Използвате остаряла версия. Можете да обновите Jappix до по-новата налична версия (%s), като натиснете тук!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Вашата версия на програмата изглежда е най-новата налична, но по желание можете да проверявате ръчно за обновления (ъпдейти), като натиснете тук."
+
+msgid "Check for updates"
+msgstr "Проверка за обновления (ъпдейти)"
+
+msgid "Update in progress"
+msgstr "В процес на обновление (ъпдейтване)..."
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix е обновен: сега използвате най-новата версия. Приятно ползване!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Обновяването е неуспешно! Моля, опитайте отново по-късно!"
+
+msgid "Downloading package..."
+msgstr "Изтегляне на пакета..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Премахване/изтриване на настоящите системни файлове на Jappix..."
+
+msgid "Extracting package..."
+msgstr "Извличане на пакета..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Презареждане на дървовидната структура на хранилищните папки..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix е вече обновен до най-новата версия!"
+
+msgid "Aborted: socket error!"
+msgstr "Прекъсната операция: цокълна (socket) грешка!"
+
+msgid "Aborted: buffer error!"
+msgstr "Неуспешна операция: буферна грешка!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Неуспех: не всичко е записваемо (writable)!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Операцията е неуспешна: пакетът не може да се извлече!"
+
+msgid "Visits"
+msgstr "Посещения"
+
+msgid "Daily"
+msgstr "дневно"
+
+msgid "Weekly"
+msgstr "седмично"
+
+msgid "Monthly"
+msgstr "месечно"
+
+msgid "Yearly"
+msgstr "годишно"
+
+msgid "Size"
+msgstr "Големина"
+
+msgid "Clean everything"
+msgstr "Изчистване на всичко/-и"
+
+msgid "Purge cache"
+msgstr "Изтриване на кеша (cache)"
+
+msgid "Purge logs"
+msgstr "Изтриване на дневниците (logs)"
+
+msgid "Purge updates"
+msgstr "Изтриване/очистване на обновления"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Папката за съхранение, която искахте да прочистите, е опразнена!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Поддържайте вашия Jappix възел свеж и бърз като прочиствате хранилищните папки често!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Качете (ъплоуднете) ваша музика (позволени файлови формати: Ogg Vorbis, MP3 или WAV), за да можете да я слушате в Jappix."
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Файлът, който искате да качите (ъплоуднете) трябва да е по-малък от %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Следете какво потребителите ви съхраняват на вашия сървър и премахвайте/изтривайте нежелателно съдържание чрез този инструмент/помощник."
+
+msgid "Title"
+msgstr "Заглавие"
+
+msgid "Artist"
+msgstr "Изпълнител/автор"
+
+msgid "Album"
+msgstr "Албум"
+
+msgid "File"
+msgstr "Файл"
+
+msgid "Upload"
+msgstr "Качване"
+
+msgid "The folder is empty."
+msgstr "Тази папка/директория е празна."
+
+msgid "The music could not be received, please retry!"
+msgstr "Музикалният файл не може да бъде получен, моля, пробвайте отново!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Това е невалиден музикален (аудио) файл, моля, прекодирайте (транскодирайте) файла към формати като Ogg Vorbis, MP3 или WAV!"
+
+msgid "Your music has been added!"
+msgstr "Музиката ви е добавена!"
+
+msgid "The selected elements have been removed."
+msgstr "Избраните елементи са премахнати/изтрити."
+
+msgid "You must select elements to remove!"
+msgstr "Трябва да изберете елементи за премахване!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "С този инструмент можете да добавите нов потребител или да промените парола (за това е нужно да въведете потребителското име/псевдоним на съществуващ потребител). Моля, използвайте силна (сигурна) парола!"
+
+msgid "Manage"
+msgstr "Управление"
+
+msgid "List"
+msgstr "Списък"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "С този инструмент/помощник можете да премахвате/изтривате потребители. Обърнете внимание на това, че не можете да премахнете потребител от системата, ако той е единственият съществуващ/вписан."
+
+msgid "The user has been added!"
+msgstr "Потребителят е добавен!"
+
+msgid "The chosen users have been removed."
+msgstr "Избраните потребители са премахнати."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Трябва да изберете един или повече потребители, които искате да премахнете от списъка!"
+
+msgid "Yesterday"
+msgstr "вчера"
+
+msgid "%s days ago"
+msgstr "преди %s дни"
+
+msgid "User currently active"
+msgstr "Потребителят е активен в момента"
+
+msgid "Last seen: %s"
+msgstr "Последно видян(и): %s"
+
+msgid "Inactive since: %s"
+msgstr "Неактивен от: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Приятелят ви изглежда не е получил вашето съобщение/-я!"
+
+msgid "Static content server"
+msgstr "Статичен сървър за съдържанието"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Това е статичният сървър за съдържанието за %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Предложени приятели"
+
+msgid "Check all"
+msgstr "Маркиране/избиране на всички"
+
+msgid "Uncheck all"
+msgstr "Размаркиране/премахване на всички"
+
+msgid "Choose"
+msgstr "Избиране"
+
+msgid "List name"
+msgstr "Име на списъка"
+
+msgid "Allow"
+msgstr "Позволяване"
+
+msgid "Deny"
+msgstr "Отказване/отхвърляне"
+
+msgid "Group"
+msgstr "Група"
+
+msgid "Subscription"
+msgstr "Абонамент"
+
+msgid "Both"
+msgstr "И двамата/двете"
+
+msgid "From"
+msgstr "От"
+
+msgid "Everybody"
+msgstr "Всички"
+
+msgid "Send messages"
+msgstr "Изпращане на съобщения"
+
+msgid "Send queries"
+msgstr "Изпращане на заявки"
+
+msgid "See my status"
+msgstr "Разглеждане на моя статус"
+
+msgid "Send his/her status"
+msgstr "Изпращане на неговия/нейния статус"
+
+msgid "Everything"
+msgstr "Всичко/-и"
+
+msgid "Item"
+msgstr "Номер"
+
+msgid "Order"
+msgstr "Ред"
+
+msgid "Active for this session"
+msgstr "Активен за тази сесия"
+
+msgid "Always active"
+msgstr "Винаги активен"
+
+msgid "User directory"
+msgstr "Потребителска директория"
+
+msgid "Search a friend"
+msgstr "Търсене за приятел"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Изисканата възможност не е имплементирана от получателя или сървъра и поради това не може да бъде обработена."
+
+msgid "This is a repeat from %s"
+msgstr "Това е повторение от %s"
+
+msgid "Loading comments..."
+msgstr "Зареждане на коментарите..."
+
+msgid "Type your comment here..."
+msgstr "Въведете вашия коментар тук..."
+
+msgid "Could not get the comments!"
+msgstr "Коментарите не могат да бъдат заредени!"
+
+msgid "Show comments"
+msgstr "Показване на коментарите"
+
+msgid "Send him/her a message"
+msgstr "Изпращане на съобщение за него/нея"
+
+msgid "Start a chat with him/her"
+msgstr "Започване на чат с него/нея"
+
+msgid "Media integration"
+msgstr "Медийна интеграция"
+
+msgid "Comments locked!"
+msgstr "Коментарите са заключени!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Въведете нещо, което бихте искали да споделите с вашите приятели..."
+
+msgid "changed his/her nickname to %s"
+msgstr "промени своя псевдоним на %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix (Джапикс) е некомерсиална (non-profit) социална платформа, която е достъпно навсякъде [стига да имате компютър и активна Интернет връзка], по всяко време, когато пожелаете, и с която можете да комуникирате с когото поискате."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/cs/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/cs/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..6b1bb2d
Binary files /dev/null and b/jappixmini/jappix/lang/cs/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/cs/LC_MESSAGES/main.po b/jappixmini/jappix/lang/cs/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..a1a6272
--- /dev/null
@@ -0,0 +1,1870 @@
+# Czech translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Ve vašem prohlížeči chybí JavaScript, takže nebude možné spustit Jappix! Prosím napravte to."
+
+msgid "An open social network"
+msgstr "Otevřená sociální síť"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Činnost Jappixe byla přerušena buď chybou ve spojenim , programu nebo nesprávnými přihlašovacími údaji (zkontrolujte vaše přihlašovací údaje), omlouváme se za komplikace"
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Seznam položek na tomto cloud serveru není možné získat!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Vaše heslo bylo změněno, nyní se můžete přihlásit k vašemu účtu s novými údaji."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Váš XMPP účet byl zrušen, nashledanou!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Byli jste odhlášeni z vašeho XMPP účtu, přejeme pěkný den!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Zdá se, že místnost do které vstoupujete neexistuje. Nejprve jí založte!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Skupinový rozhovor byl odstraněn, nyí ho může vytvořit někdo jiný."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Uživatel, kterého chcete zastihnout se v této místnosti nenachází."
+
+msgid "Please enter the group chat address to join."
+msgstr "Prosím, vložte adresu skupinového rozhovoru ke kterému se chcete připojit."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Prosím, vložte přezdívku pro připojení do %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Místnost (%s) je chráněna heslem."
+
+msgid "Your browser is out of date!"
+msgstr "Váš prohlížeš je zastaralý."
+
+msgid "Last %s version is better!"
+msgstr "Poslední %s verze je lepší!"
+
+msgid "Login"
+msgstr "Přihlášení"
+
+msgid "Register"
+msgstr "Registrace"
+
+msgid "Here we go!"
+msgstr "Pojďme na to!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Heslo"
+
+msgid "Remember me"
+msgstr "Zapamatuj si mě"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Tato možnost je zakázána, nelze jí použít!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Byli jste odhlášeni, potože se vyskytly potíže se sítí. Co si přejete udělat?"
+
+msgid "Reconnect"
+msgstr "Znovu připojit"
+
+msgid "Messages"
+msgstr "Zprávy"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Nastavení"
+
+msgid "Disconnect"
+msgstr "Odpojit se"
+
+msgid "Filter"
+msgstr "Filtr"
+
+msgid "Add a friend"
+msgstr "Přidat kamaráda"
+
+msgid "Your groupchats"
+msgstr "Vaše skupinové rozhovory"
+
+msgid "Manage your favorite groupchats"
+msgstr "Spravovat vaše blíbené skupinové rozhovory"
+
+msgid "More stuff"
+msgstr "Další možnosti"
+
+msgid "Show all friends"
+msgstr "Zobrazit všechny kamarády"
+
+msgid "Only show connected friends"
+msgstr "Zobrazit pouze připojené kamarády"
+
+msgid "Message archives"
+msgstr "Archiv zpráv"
+
+msgid "Date"
+msgstr "Datum"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Prosím, vyperte kamaráda pro zobrazení historie rozhovoru."
+
+msgid "Nothing found for: %s"
+msgstr "Žádný výsledek pro: %s"
+
+msgid "A short message?"
+msgstr "Krátká zpráva?"
+
+msgid "How are you?"
+msgstr "Jak se vede ?"
+
+msgid "What are you doing?"
+msgstr "Co děláš?"
+
+msgid "Join a chat"
+msgstr "Zahájit rozhovor"
+
+msgid "Status"
+msgstr "Stav"
+
+msgid "Available"
+msgstr "Přítomen"
+
+msgid "Talkative"
+msgstr "Hovorný"
+
+msgid "Away"
+msgstr "Pryč"
+
+msgid "Not available"
+msgstr "Nedostupný"
+
+msgid "Busy"
+msgstr "Nerušit"
+
+msgid "Mood"
+msgstr "Nálada"
+
+msgid "None"
+msgstr "Neuvedena"
+
+msgid "Crazy"
+msgstr "Bláznivý"
+
+msgid "Excited"
+msgstr "Vzrušený"
+
+msgid "Playful"
+msgstr "Hravý"
+
+msgid "Happy"
+msgstr "Šťastný"
+
+msgid "Shocked"
+msgstr "Šokovaný"
+
+msgid "Hot"
+msgstr "Nažhavený"
+
+msgid "Sad"
+msgstr "Smutný"
+
+msgid "Amorous"
+msgstr "Zamilovaný"
+
+msgid "Confident"
+msgstr "Důvěřivý"
+
+msgid "Activity"
+msgstr "Činnost"
+
+msgid "Chores"
+msgstr "Nakupuje"
+
+msgid "Drinking"
+msgstr "Pije"
+
+msgid "Eating"
+msgstr "Jí"
+
+msgid "Exercising"
+msgstr "Cvíčí"
+
+msgid "Grooming"
+msgstr "Pečuje"
+
+msgid "Appointment"
+msgstr "Schůzka"
+
+msgid "Inactive"
+msgstr "Nečinný"
+
+msgid "Relaxing"
+msgstr "Relaxuje"
+
+msgid "Talking"
+msgstr "Hovoří"
+
+msgid "Traveling"
+msgstr "Cestuje"
+
+msgid "Working"
+msgstr "Pracuje"
+
+msgid "View profile"
+msgstr "Zobrazit profil"
+
+msgid "Repeat this notice"
+msgstr "Opakovat toto upozornění"
+
+msgid "Remove this notice"
+msgstr "Odstranit upozornění"
+
+msgid "Your profile"
+msgstr "Váš profil"
+
+msgid "Identity"
+msgstr "Osobní údaje"
+
+msgid "Profile image"
+msgstr "Fotografie k profilu"
+
+msgid "Others"
+msgstr "Ostatní"
+
+msgid "Personal"
+msgstr "Osobní"
+
+msgid "Complete name"
+msgstr "Celé jméno"
+
+msgid "Nickname"
+msgstr "Přezdívka"
+
+msgid "First name"
+msgstr "Jméno"
+
+msgid "Last name"
+msgstr "Příjmení"
+
+msgid "Date of birth"
+msgstr "Datum narození"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefon"
+
+msgid "Website"
+msgstr "Webová stránka"
+
+msgid "Current"
+msgstr "Současná"
+
+msgid "Delete"
+msgstr "Smazat"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Jaká škoda! Nemáte nastavenou fotografii u profilu ve vaší vizitce!"
+
+msgid "Address"
+msgstr "Adresa"
+
+msgid "Street"
+msgstr "Ulice"
+
+msgid "City"
+msgstr "Město"
+
+msgid "Postal code"
+msgstr "PSČ"
+
+msgid "Country"
+msgstr "Země"
+
+msgid "Biography"
+msgstr "O mě"
+
+msgid "Important notice"
+msgstr "Důležité upozornění"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Buďte opatrní, informace, které vyplníte v profilu jsou přístupné každému (i tomu, komu nechcete)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Není všechno v XMPP jen soukromé; toto je jednou z těch věcí, které nejsou, váš veřejný profil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Vřele doporučujeme nahrát obrázek k profilu (%s maximálně), například vaší fotografii, aby vás kamarádi lépe poznali. "
+
+msgid "Save"
+msgstr "Uložit"
+
+msgid "Cancel"
+msgstr "Zrušit"
+
+msgid "Edit options"
+msgstr "Upravit nastavení"
+
+msgid "Channel"
+msgstr "Kanál"
+
+msgid "Commands"
+msgstr "Příkazy"
+
+msgid "Sounds"
+msgstr "Zvuky"
+
+msgid "Privacy"
+msgstr "Soukromí"
+
+msgid "Message archiving"
+msgstr "Archivace zpráv"
+
+msgid "Store a history of your chats"
+msgstr "Ukládat historii vašich rozhovorů"
+
+msgid "Geolocation"
+msgstr "Geologická poloha"
+
+msgid "Empty"
+msgstr "Odstranit"
+
+msgid "Empty channel"
+msgstr "Vymazat kanál"
+
+msgid "Persistent"
+msgstr "Natrvalo"
+
+msgid "Maximum notices"
+msgstr "Maximum upozornění"
+
+msgid "Account"
+msgstr "Účet"
+
+msgid "Change password"
+msgstr "Změnit heslo"
+
+msgid "Delete account"
+msgstr "Zrušit účet"
+
+msgid "Old"
+msgstr "Staré"
+
+msgid "New (2 times)"
+msgstr "Nové (2 krát)"
+
+msgid "Continue"
+msgstr "Pokračovat"
+
+msgid "To"
+msgstr "Komu"
+
+msgid "Close"
+msgstr "Zavřít"
+
+msgid "unknown"
+msgstr "neznámá"
+
+msgid "Unavailable"
+msgstr "Odpojen"
+
+msgid "is now"
+msgstr ""
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Prosím čekejte, než se váš avatar nahraje ..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Zde je! Nový krásný obrázek profilu!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Soubor s obrázkem není podporován nebo je příliš velký."
+
+msgid "Reply"
+msgstr "Odpovědět"
+
+msgid "Error"
+msgstr "Chyba"
+
+msgid "Click here to solve the error"
+msgstr "KLikněte zde pro řešení problému"
+
+msgid "You"
+msgstr "Ty"
+
+msgid "Remove"
+msgstr "Odstranit"
+
+msgid "Rename"
+msgstr "Přejmenovat"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Ahoj, Já jsem %s, chci si Tě přidat jako kamaráda."
+
+msgid "Smiley insertion"
+msgstr "Vložit smajlíka"
+
+msgid "Change style"
+msgstr "Písmo"
+
+msgid "Text in bold"
+msgstr "Tučné"
+
+msgid "Text in italic"
+msgstr "Kurzíva"
+
+msgid "Underlined text"
+msgstr "Podtržené"
+
+msgid "Save chat"
+msgstr "Uložit rozhovor"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Klikni na nasledující odkaz pro vytvoření logu rozhovoru, a počkej. Potom klikni znovu ke stažení souboru."
+
+msgid "This chat is empty!"
+msgstr "Tento rozhovor je prázdný!"
+
+msgid "Generate file!"
+msgstr "Vygeneruj soubor!"
+
+msgid "Download file!"
+msgstr "Stažení souboru!"
+
+msgid "Clean current chat"
+msgstr "Vyčistit probíhající rozhovor"
+
+msgid "View chat history"
+msgstr "Zobrazit historii rozhovoru"
+
+msgid "Show user profile"
+msgstr "Zobrazit profil uživatele"
+
+msgid "Add this contact to your friends"
+msgstr "Přidej tento kontakt mezi své kamarády"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Přidej tento skupinový rozhovor do oblíbených"
+
+msgid "All tabs"
+msgstr "Všechny listy"
+
+msgid "Close this tab"
+msgstr "Zavřít tento list"
+
+msgid "no subject defined for this room."
+msgstr "Není nastaven předmět pro tuto místnost"
+
+msgid "Administration panel for this room"
+msgstr "Panel administrace pro tuto místnost"
+
+msgid "Moderators"
+msgstr "Moderátoři"
+
+msgid "Participants"
+msgstr "Členové"
+
+msgid "Visitors"
+msgstr "Návštěvníci"
+
+msgid "Manage favorite rooms"
+msgstr "Spravovat oblíbené skupinové rozhovory"
+
+msgid "Change favorites"
+msgstr "Změnit oblíbené"
+
+msgid "Search a room"
+msgstr "Najít místnost"
+
+msgid "Select a favorite"
+msgstr "Vyberte oblíbenou"
+
+msgid "Getting the name..."
+msgstr "Získávám jméno ..."
+
+msgid "Gateway"
+msgstr "Brána"
+
+msgid "Name"
+msgstr "Jméno"
+
+msgid "Room"
+msgstr "Místnost"
+
+msgid "Add"
+msgstr "Přidat"
+
+msgid "Edit"
+msgstr "Upravit"
+
+msgid "Search a room on"
+msgstr "Najít místnost na"
+
+msgid "No room found on this server."
+msgstr "Na tomto serveru nebyla nalezena žádná místnost."
+
+msgid "Service discovery"
+msgstr "Zjištění služeb"
+
+msgid "Server to query"
+msgstr "Prohledávaný server"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Promiňte, ale hledaný výraz nebyl nalezen!"
+
+msgid "Accounts"
+msgstr "Účty"
+
+msgid "Authentications"
+msgstr "Ověřování"
+
+msgid "Automation"
+msgstr "Automaticky"
+
+msgid "Clients"
+msgstr "Klienti"
+
+msgid "Collaboration"
+msgstr "Spolupráce"
+
+msgid "Components"
+msgstr "Komponenty"
+
+msgid "Rooms"
+msgstr "Místnosti"
+
+msgid "Directories"
+msgstr "Adresáře"
+
+msgid "Gateways"
+msgstr "Brány"
+
+msgid "News"
+msgstr "Novinky"
+
+msgid "Hierarchy"
+msgstr "Hierarchie"
+
+msgid "Proxies"
+msgstr "Proxy server"
+
+msgid "Publication/Subscription"
+msgstr "Publikování/Odebírání"
+
+msgid "Storage"
+msgstr "Úložiště"
+
+msgid "Service offline or broken"
+msgstr "Služba je vypnutá nebo nedostupná"
+
+msgid "Your inbox"
+msgstr "Vaše schránka"
+
+msgid "Available actions"
+msgstr "Dostupné akce"
+
+msgid "Clean"
+msgstr "Vyčistit"
+
+msgid "New"
+msgstr "Nová"
+
+msgid "Received"
+msgstr "Přijaté"
+
+msgid "Subject"
+msgstr "Předmět"
+
+msgid "Content"
+msgstr "Obsah"
+
+msgid "Send message"
+msgstr "Odeslat zprávu"
+
+msgid "Your inbox is empty."
+msgstr "Vaše schránka je prázdná."
+
+msgid "MUC administration"
+msgstr "Administrace MUC"
+
+msgid "You administrate this room"
+msgstr "Spravujte tuto místnost"
+
+msgid "Enter new subject"
+msgstr "Vložte nový přednět"
+
+msgid "Configuration"
+msgstr "Nastavení"
+
+msgid "Authorizations"
+msgstr "Povolení"
+
+msgid "Member list"
+msgstr "Seznam členů"
+
+msgid "Owner list"
+msgstr "Seznam vlastníků"
+
+msgid "Administrator list"
+msgstr "Seznam správců"
+
+msgid "Outcast list"
+msgstr "Seznam nežádoucích"
+
+msgid "Add an input"
+msgstr "Přidej člena"
+
+msgid "Destroy this MUC"
+msgstr "Zrušit tento MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Ano, pojďme na to!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Váš kamarád sleduje rozhovor."
+
+msgid "Your friend is writing a message..."
+msgstr "Váš kamarád píše ..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Váš kamarád přestal psát."
+
+msgid "Your friend is doing something else."
+msgstr "Váš kamarád se věnuje něčemu jinému."
+
+msgid "Your friend closed the chat."
+msgstr "Váš kamarád ukončil rozhovor."
+
+msgid "Requesting this service..."
+msgstr "Žádám o tuto službu ..."
+
+msgid "Loading"
+msgstr "Načítání"
+
+msgid "joined the chat room"
+msgstr "Vstoupit do místnosti"
+
+msgid "left the chat room"
+msgstr "opustit místnost"
+
+msgid "no status"
+msgstr "bez statusu"
+
+msgid "has been kicked"
+msgstr "byl vyloučen"
+
+msgid "has been banned"
+msgstr "byl zakázán"
+
+msgid "no reason"
+msgstr "bez důvodu"
+
+msgid "Communicate with the entire world!"
+msgstr "Komunikujte s celým světem!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Umožní vám být v kontaktu s milióny uživateli, kteří právě využívají XMPP síť stejně jako vy s Jabbixem. Přidpojte se ke komunitě a zůstaňte svobodní."
+
+msgid "Hi there!"
+msgstr "Ahoj!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Vítejte na %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Přihlaste se ke svému již existujícímu XMPP účtu nebo si zaregistrujte zdarma nový!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix je open-source projekt od PostPro, neziskové organizace, která poskytuje velkou podporu."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Přihlaš se ke svému již existujícímu XMPP účtu. Také můžeš použít %s pro připojení ke skupinovému rozhovoru."
+
+msgid "Previous"
+msgstr "Předchozí"
+
+msgid "General"
+msgstr "Obecné"
+
+msgid "Advanced"
+msgstr "Rozšířené"
+
+msgid "Resource"
+msgstr "Zdroj"
+
+msgid "Priority"
+msgstr "Priorita"
+
+msgid "Low"
+msgstr "Nízká"
+
+msgid "Medium"
+msgstr "Střední"
+
+msgid "High"
+msgstr "Vysoká"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Zadejte název skupinového rozhovoru ke kterému se chcete připojit a zvolte si přezdívku. Nebo se můžete vrátit na %s."
+
+msgid "login page"
+msgstr "přihlašovací stránku"
+
+msgid "Share this link with your friends:"
+msgstr "Sdílejte tento odkaz s kamarády:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Zaregistruj si nový XMPP účet a spoj se s kamarády ve vlastní sociální síti. Je to jednoduché!"
+
+msgid "Required"
+msgstr "Povinné"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Jste zaregistrivání, toto je vaše XMPP adresa:"
+
+msgid "Manager"
+msgstr "Správce"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Šifrovaně"
+
+msgid "Unencrypted"
+msgstr "Bez šifrování"
+
+msgid "Where are you?"
+msgstr "Kde jsi?"
+
+msgid "What's up with you?"
+msgstr "Co je s tebou?"
+
+msgid "Fetching the social channel..."
+msgstr "Stahuji kanál ..."
+
+msgid "You are synchronized with your network."
+msgstr "Nyní jste synchronizovaný s vaší sítí."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Nelze nic odesílat: můžete pouze přijímat zprávy!"
+
+msgid "Media viewer"
+msgstr "Prohlížeč médií"
+
+msgid "Browse"
+msgstr "Prohlížet"
+
+msgid "Command"
+msgstr "Příkaz"
+
+msgid "Subscribe"
+msgstr "Registrace"
+
+msgid "Join"
+msgstr "Připojit"
+
+msgid "Automatic"
+msgstr "Automaticky"
+
+msgid "Search"
+msgstr "Hledat"
+
+msgid "No result!"
+msgstr "Nic nenalezeno!"
+
+msgid "No notifications."
+msgstr "Žádné upozornění."
+
+msgid "would like to add you as a friend."
+msgstr "si vás chce přidat jako kamaráda."
+
+msgid "would like you to join this chatroom:"
+msgstr "žádá vás aby jste vstoupili do místnosti."
+
+msgid "Do you accept?"
+msgstr "Souhlasíte?"
+
+msgid "Yes"
+msgstr "Ano"
+
+msgid "No"
+msgstr "Ne"
+
+msgid "would like to get authorization."
+msgstr "žádá o povolení."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Přejete si vidět kamarády, které vám %s navrhuje?"
+
+msgid "Submit"
+msgstr "Odeslat"
+
+msgid "Client"
+msgstr "Klient"
+
+msgid "System"
+msgstr "Systém"
+
+msgid "Local time"
+msgstr "Místní čas"
+
+msgid "Comments"
+msgstr "Komentáře"
+
+msgid "User profile"
+msgstr "Profil uživatele"
+
+msgid "See his/her position on the globe"
+msgstr "Zobraz jeho/její polohu na zeměkouli"
+
+msgid "Confirm"
+msgstr "Ověřit"
+
+msgid "anonymous mode"
+msgstr "anonymní mód"
+
+msgid "Groups"
+msgstr "Skupiny"
+
+msgid "Unclassified"
+msgstr "Nezařazené"
+
+msgid "Authorize"
+msgstr "Oprávnit"
+
+msgid "Ask for authorization"
+msgstr "Požádat o oprávnění"
+
+msgid "Unblock"
+msgstr "Odblokovat"
+
+msgid "Prohibit"
+msgstr "Zakázat"
+
+msgid "Block"
+msgstr "Blokovat"
+
+msgid "Chat"
+msgstr "Rozhovor"
+
+msgid "Groupchat"
+msgstr "Skupinový rozhovor"
+
+msgid "Jappix Mobile"
+msgstr "Jabbix pro Mobil"
+
+msgid "Desktop"
+msgstr "Počítač"
+
+msgid "Mobile"
+msgstr "Mobil"
+
+msgid "Please wait..."
+msgstr "Čekejte prosím ..."
+
+msgid "Please enable JavaScript"
+msgstr "Prosím povolte JavaScript"
+
+msgid "Your channel"
+msgstr "Váš kanál"
+
+msgid "Channel of"
+msgstr "Kanál uživatele"
+
+msgid "More notices..."
+msgstr "Další upozornění ..."
+
+msgid "Attach a file"
+msgstr "Připojit soubor"
+
+msgid "Send"
+msgstr "Odeslat"
+
+msgid "Unattach the file"
+msgstr "Odebrat soubor"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Nastala chyba během nahrávání souboru: buď je příliš velký (%s maximálně) nebo není povolen!"
+
+msgid "Authorization failed"
+msgstr "Autorizace se nezdařila"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrace se nezdařila, zvolte prosím jiné uživatelské jméno"
+
+msgid "Service unavailable"
+msgstr "Služba je nedostupná"
+
+msgid "Internal server error, try later"
+msgstr "Vnitřní chyba serveru, zkuste později"
+
+msgid "Your form has been sent."
+msgstr "Váš formulář byl odeslán."
+
+msgid "Application"
+msgstr "Aplikace"
+
+msgid "XMPP links"
+msgstr "XMPP odkaz"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Otevřít XMPP odkaz pomocí Jappix"
+
+msgid "changed the subject to:"
+msgstr "změnit předmět na:"
+
+msgid "Welcome!"
+msgstr "Vítejte!"
+
+msgid "Friends"
+msgstr "Kamarádi"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Vítejte v Jappix, vaší vlastní sociální síti!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Dříve než jí začnete používat, měli by jste upravit některá nastavení, vyhledat kamarády a vyplnit svůj profil."
+
+msgid "Enable notification sounds"
+msgstr "Povolit upozorňování pomocí zvuků"
+
+msgid "Share your position on the globe"
+msgstr "Sdílet svojí polohu na zeměkouli"
+
+msgid "Offline friends"
+msgstr "Odpojení kamarádi"
+
+msgid "Don't hide offline friends"
+msgstr "Neskrývat odpojené kamarády"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Použijte tento nástroj na vyhledání kamarádů na tomto serveru. Nebo je můžete přidat později."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Skvěle! Nyní můžete sdílet Jappix se svými kamarády!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Nyní, když stisknete tlačitko Uložit, následuje otevření editoru vašeho profilu."
+
+msgid "Share Jappix on %s"
+msgstr "Sdílejte Jappix na %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Používám Jappix, otevřenou sociální platformu. Jsem %s!"
+
+msgid "Unknown name"
+msgstr "Neznámé jméno"
+
+msgid "Unknown country"
+msgstr "Neznámá země"
+
+msgid "Click to enable"
+msgstr "Klikni pro povolení"
+
+msgid "Click to disable"
+msgstr "Klikni pro zakázání"
+
+msgid "Installation"
+msgstr "Instalace"
+
+msgid "Jappix installation"
+msgstr "Jappix instalace"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Vítejte v Jappix instalaci!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Tento nástroj vám pomůže rychle nainstalovat Jappix, první plnohodnotnou sociální platformu založenou na XMPP, na váš server. Nebudete dokonce potřebovat žádné technické znalosti."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Přejděme k instalačním krokům:"
+
+msgid "Welcome"
+msgstr "Vítejte"
+
+msgid "Storage configuration"
+msgstr "Nastavení úložiště"
+
+msgid "Administrator account"
+msgstr "Účet administrátora"
+
+msgid "Main configuration"
+msgstr "Hlavní nastavení"
+
+msgid "Hosts configuration"
+msgstr "Nastavení hostitele"
+
+msgid "Services installation"
+msgstr "Instalace služeb"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Pokud se tento jazyk (%1s) neshoduje s vaším, můžete nechat Jappix mluvit jiným jazykem %2s. Volba bude uložena."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Pokud potřebujete pomoci s instalací a nastavením Jappix, můžete využít dokumentaci, kterou naleznete zde:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Nastal čas vybudovat vlastní sociální síť: stačí přejít k nasledujícímu kroku!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix ukládá natrvalo data (sdílené soubory, vaše vlastní hudba a konfigurace) do jediného zabezpečeného adresáře. "
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix musí mít oprávnění zapisovat do tohoto adresáře pro vytvoření vlastních podadresářů.Pokud tomu tak není, je třeba nastavit oprávnění na %1s a nebo nastavit vlastníka adresáře na %2s (závisí to na vašem nastavení)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Do adresáře je povolen zápis, můžete pokračovat!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix vám úmožňuje spravovat vaší konfiguraci, instalovat pluginy nebo vyhledávat aktualizace. Proto je nutné si vytvořit účet administrátora ke vstupu do Správy Jappix."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Když je Jappix nainstalován, stačí kliknout na odkaz Správce na výchozí stránce pro vstup do Správy. "
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Jejda, něco vám uniklo, nebo se hesla neshodují!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix vyžaduje nastavení některých údajů. Prosím upravtel následující údaje (nebo nechte přednastavené, které většině uživatelů vyhovují)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Pokud nenastavíte povinné údaje, budou nastaveny na výchozí."
+
+msgid "User"
+msgstr "Uživatel"
+
+msgid "Service"
+msgstr "Služba"
+
+msgid "Service name"
+msgstr "Název služby"
+
+msgid "Service description"
+msgstr "Popis služby"
+
+msgid "Connection"
+msgstr "Připojení"
+
+msgid "Lock the host"
+msgstr "Uzamknout hostitele"
+
+msgid "Anonymous mode"
+msgstr "Anonymní mód"
+
+msgid "Registration allowed"
+msgstr "Registrace povolena"
+
+msgid "Use a proxy"
+msgstr "Použít proxy"
+
+msgid "Encryption"
+msgstr "Šifrování"
+
+msgid "HTTPS storage"
+msgstr "HTTPS úložiště"
+
+msgid "Force HTTPS"
+msgstr "Vynutit HTTPS"
+
+msgid "Compression"
+msgstr "Komprese"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Tato stránka vám pomůže nastavit výchozího hostitele. Použijte přednastavené hodnoty, pokud chcete využívat oficiální službu hostitele."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "BOSH server v podstatě předává informace mezi Jappix klientem a XMPP serverem a je nutný vzhledem k technickému omezení."
+
+msgid "Main host"
+msgstr "Hlavní hostitel"
+
+msgid "Groupchat host"
+msgstr "Hostitel skupinových rozhovorů (Groupchat host)"
+
+msgid "Anonymous host"
+msgstr "Anonymní host"
+
+msgid "Directory host"
+msgstr "Directory host"
+
+msgid "BOSH host"
+msgstr "BOSH host"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Můžete nainstalovat další software pro rozšíření funkcí vašeho Jappix. Některé jiné funkce můžete upravit, zejména z důvodů bezpečnosti, protože byly nastaveny na vychozí hodnoty."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "K tomu je nutný přístup na konzoli serveru a mít oprávnění root uživatele, Jappix bude pracovat i bez těchto dalších modulů, ale některé funkce budou nedostupné."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Po ukončení nastavení Jappix vygeneruje cache soubory. Toto může nějaký čas trvat, počkejte až se zobrazí aplikace a do té doby nemačkejte jakoukoli klávesu."
+
+msgid "Thanks for using Jappix!"
+msgstr "Děkujeme za používání Jappix!"
+
+msgid "Next"
+msgstr "Další"
+
+msgid "Finish"
+msgstr "Dokončit"
+
+msgid "Check again"
+msgstr "Opakovat"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Do adresáře nelze zapisovat, nastavte oprávnění na %s."
+
+msgid "%s is installed on your system."
+msgstr "%s je nainstalován na vašem systému."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s není na vašem systému nainstalován, nainstalujte %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP maximální velikost nahrávaného souboru je dostatečná (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP maximální velikost nahrávaného souboru není dostatečná (%1s), měli byste jí nastavit na %2s v %3s."
+
+msgid "Jappix manager"
+msgstr "Jappix správce"
+
+msgid "Manager access"
+msgstr "Přístup ke Správě"
+
+msgid "Statistics"
+msgstr "Statistika"
+
+msgid "Hosts"
+msgstr "Hostitelé"
+
+msgid "Design"
+msgstr "Vzhled"
+
+msgid "Repeat"
+msgstr "Opakovat"
+
+msgid "All"
+msgstr "Vše"
+
+msgid "Horizontal"
+msgstr "Horizontálně"
+
+msgid "Vertical"
+msgstr "Vertikálně"
+
+msgid "Center"
+msgstr "Střed"
+
+msgid "Left"
+msgstr "Vlevo"
+
+msgid "Right"
+msgstr "Vpravo"
+
+msgid "Top"
+msgstr "Nahoře"
+
+msgid "Bottom"
+msgstr "Dole"
+
+msgid "Adapt"
+msgstr "Přizpůsobit"
+
+msgid "Color"
+msgstr "Barva"
+
+msgid "Users"
+msgstr "Uživatelé"
+
+msgid "Updates"
+msgstr "Aktualizace"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Omezený přístup: pouze oprávnění uživatelé mohou spravovat tento Jappix uzel."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Prosím požijte následující formulář pro přihlášení do administrátorského rozhraní."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Pro zvýšení bezpečnosti je přihlášení časově omezeno a pokud zavřetel prohlížeč budete odhlášeni."
+
+msgid "Credentials"
+msgstr "Ověření"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Jste odhlášeni, Nashledanou!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Jejda, nejste platný správce. Zkontrolujte, vaše přihlašovací údaje!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Základní statisticky o některých důležitých údajích zpracováváných Jappixem najdete níže."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Změna konfiguraci vašeho Jabbix uzlu pomocí správce."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Změnit nastavení XMPP hostitelů, které tento Jappix uzel využívá, lze v tomto panelu."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Všechny soubory uložené na tomot Jappix uzlu můžete spravovat v tomto panelu: zvolte podadresář a můžete upravovat obsah."
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix je zcela přizpůsobitelný: jeho vzhled si můžete zde upravit."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Toto není povolený obrázek, prosím použijte PNG, GIF nebo JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Obrázek nebyl přijat, přejete si akci zopakovat?"
+
+msgid "Your image was added to the list!"
+msgstr "Váš obrázek byl přidán do seznamu!"
+
+msgid "Changes saved!"
+msgstr "Změny byly uloženy!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Na tomto Jappix uzlu lze zadat více správců. Také lze změnit heslo v tomto panelu."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Aktualizuj Jappix uzel v tohoto panelu nebo zjisti, zda není dostupná nové verze. Informace o poslední verzi se také zobrazí (anglicky)."
+
+msgid "Access statistics"
+msgstr "Statistiky přístupů"
+
+msgid "Share statistics"
+msgstr "Statistiky sdílení"
+
+msgid "Other statistics"
+msgstr "Oatatní statistiky"
+
+msgid "January"
+msgstr "Leden"
+
+msgid "February"
+msgstr "Únor"
+
+msgid "March"
+msgstr "Březen"
+
+msgid "April"
+msgstr "Duben"
+
+msgid "May"
+msgstr "Květen"
+
+msgid "June"
+msgstr "Červen"
+
+msgid "July"
+msgstr "Červenec"
+
+msgid "August"
+msgstr "Srpen"
+
+msgid "September"
+msgstr "Září"
+
+msgid "October"
+msgstr "Říjen"
+
+msgid "November"
+msgstr "Listopad"
+
+msgid "December"
+msgstr "Prosinec"
+
+msgid "Monday"
+msgstr "Pondělí"
+
+msgid "Tuesday"
+msgstr "Úterý"
+
+msgid "Wednesday"
+msgstr "Středa"
+
+msgid "Thursday"
+msgstr "Čtvrtek"
+
+msgid "Friday"
+msgstr "Pátek"
+
+msgid "Saturday"
+msgstr "Sobota"
+
+msgid "Sunday"
+msgstr "Neděle"
+
+msgid "Total"
+msgstr "Celkem"
+
+msgid "Cache"
+msgstr "Keš"
+
+msgid "Logs"
+msgstr "Logy"
+
+msgid "Music"
+msgstr "Hudba"
+
+msgid "Backgrounds"
+msgstr "Pozadí"
+
+msgid "Share"
+msgstr "Sdílení"
+
+msgid "Background"
+msgstr "Pozadí"
+
+msgid "Notice"
+msgstr "Upozornění"
+
+msgid "Your design preferences have been saved!"
+msgstr "Nastavení vašeho vzhledu bylo uloženo."
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Zkontrolujte údaje: nejsou kompletní!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "V tomto panelu lze nastavit vzhled vašeho Jappix uzlu. Lze nastavit vlastní barvu či uložený obrázek. Nechte volnost své tvořivosti!"
+
+msgid "Use default background"
+msgstr "Použít výchozí pozadí"
+
+msgid "Use your own image"
+msgstr "Použít vlastní obrázek"
+
+msgid "Select a background to use and change the display options."
+msgstr "Zvolte pozadí a upravte nastavení zobrazení."
+
+msgid "Use your own color"
+msgstr "Použijte vlastní barvu"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Zadejte hexadecimálně barvu vašeho pozadí."
+
+msgid "Manage backgrounds"
+msgstr "Správa pozadí"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "V tomto panelu lze přidat nové pozadí do seznamu. Prosím odešlete platný obrázek."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Pokud chcete některé pozadí odstranit, použijte následující prohlížeč."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Nastavení upozornění na výchozí stránce pro všechny uživatele, např. varování, důležité oznámení či raklama."
+
+msgid "Simple notice"
+msgstr "Jednoduché upozornění"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Toto upozornění umožňuje pouze jednoduchý text. Žádný kód není povolen."
+
+msgid "Advanced notice"
+msgstr "Rozšířené upozornění"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Vaše upozornění lze upravit vložením HTML, CSS a JavaScript, ale je třeba i kód stylu."
+
+msgid "Available updates"
+msgstr "Dostupné aktualizace"
+
+msgid "What's new?"
+msgstr "Co je nového?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Do adresáře k ukládání nelze zapisovat, prosím upravte oprávnění!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s může způsobit problémy s proxy, prosím zvyšte hodnotu %2s na %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Právě používáte vývojovou verzi Jappix. Aktualizujte jí z repozitáře spůštěním %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Je dostupná nová verze Jappix! Zjistěte co je v ní nového a proveďte update!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Vaše verze je zastaralá. Aktualizujte ji nyní na %s kliknutím zde!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Vaše verze se zdá být aktuální, ale je možné zkontrolovat aktualizace ručně kliknutím zde."
+
+msgid "Check for updates"
+msgstr "Dostupné aktualizace"
+
+msgid "Update in progress"
+msgstr "Prohíhá aktualizace"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jabbix byl aktualizován: právě používáte nejnovější verzi. Příjemnou zábavu!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Aktualizace selhala! Prosím opakujte později."
+
+msgid "Downloading package..."
+msgstr "Stahuji balíček ..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Odstraňování aktuálních systémových souborů Jappixe ..."
+
+msgid "Extracting package..."
+msgstr "Rozbaluji balíček ..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Obnovování stromu adresáře úložiště ..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix je aktualizován!"
+
+msgid "Aborted: socket error!"
+msgstr "Nezdařilo se: chyba soketu!"
+
+msgid "Aborted: buffer error!"
+msgstr "Nezdařilo se: chyba bufferu!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Nezdařilo se: nelze zapsat!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Nezdařilo se: nelze rozbalti balíček!"
+
+msgid "Visits"
+msgstr "Návštěvnost"
+
+msgid "Daily"
+msgstr "Denně"
+
+msgid "Weekly"
+msgstr "Týdně"
+
+msgid "Monthly"
+msgstr "Měsíčně"
+
+msgid "Yearly"
+msgstr "Ročně"
+
+msgid "Size"
+msgstr "Velikost"
+
+msgid "Clean everything"
+msgstr "Vše odstranit"
+
+msgid "Purge cache"
+msgstr "Vymazat keš"
+
+msgid "Purge logs"
+msgstr "Vymazat logy"
+
+msgid "Purge updates"
+msgstr "Vymazat aktualizace"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Odkládací adresář, který chcete vymazat je nyní prázdny!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Udržujte váš uzel Jappix čistý a rychlý, pravidelně čistěte adkládací prostor!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Nahrajte vlastní hudbu (Ogg Vorbis, MP3 or WAV) a můžete jí poslouchat v Jappixu!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Soubor který chcete nahrát nesmí být větší než %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Buďte v obraze o tom co vaši uživatelé ukládají na server a odstraňte nevhodný obsah v tomto panelu."
+
+msgid "Title"
+msgstr "Název"
+
+msgid "Artist"
+msgstr "Zpěvák/Zpěvačka"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Soubor"
+
+msgid "Upload"
+msgstr "Nahrát"
+
+msgid "The folder is empty."
+msgstr "Adresář je prázdný."
+
+msgid "The music could not be received, please retry!"
+msgstr "Hudba nebyla přijata, prosím opakujte akci!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Toto není platný hudební soubor, prosím použijte Ogg Vorbis, MP3 nebo WAV!"
+
+msgid "Your music has been added!"
+msgstr "Vaše písnička byla přidána!"
+
+msgid "The selected elements have been removed."
+msgstr "Vybrané položky budou nyní odstraněny."
+
+msgid "You must select elements to remove!"
+msgstr "Musíte vybrat položky k odstranění!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Zde lze přidat uživatele, změnit heslo (použijte existující uživatelské jméno). Zvolte silné heslo!"
+
+msgid "Manage"
+msgstr "Spravovat"
+
+msgid "List"
+msgstr "Seznam"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "V tomto panelu lze odstranit uživatele. Mějte na paměti, že nelze odstranit uživatele, pokud je poslední."
+
+msgid "The user has been added!"
+msgstr "Uživatel byl přidán!"
+
+msgid "The chosen users have been removed."
+msgstr "Zvolený uživatel byl odstraněn."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Musíte zvolit jednoho nebo více uživatelu k odstranění!"
+
+msgid "Yesterday"
+msgstr "Včera"
+
+msgid "%s days ago"
+msgstr "Před %s dny"
+
+msgid "User currently active"
+msgstr "Uživatel je nyní aktivní"
+
+msgid "Last seen: %s"
+msgstr "Naposledy viděn: %s"
+
+msgid "Inactive since: %s"
+msgstr "Nečinný od: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Zdá se, že váš kamarád nedostal vaší zprávu(y)!"
+
+msgid "Static content server"
+msgstr "Statický obsah serveru"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Toto je statický obsah serveru před %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Navrhovaní kamarádi"
+
+msgid "Check all"
+msgstr "Označit vše"
+
+msgid "Uncheck all"
+msgstr "Zrušit označení všeho"
+
+msgid "Choose"
+msgstr "Vybrat"
+
+msgid "List name"
+msgstr "Jméno seznamu"
+
+msgid "Allow"
+msgstr "Povolit"
+
+msgid "Deny"
+msgstr "Zakázat"
+
+msgid "Group"
+msgstr "Skupina"
+
+msgid "Subscription"
+msgstr "Oprávnění"
+
+msgid "Both"
+msgstr "Obojí"
+
+msgid "From"
+msgstr "Od"
+
+msgid "Everybody"
+msgstr "Všichni"
+
+msgid "Send messages"
+msgstr "Odeslat zprávu"
+
+msgid "Send queries"
+msgstr "Odeslat žádost"
+
+msgid "See my status"
+msgstr "Vidět můj status"
+
+msgid "Send his/her status"
+msgstr "Odeslat jemu/ji status"
+
+msgid "Everything"
+msgstr "Vše"
+
+msgid "Item"
+msgstr "Položka"
+
+msgid "Order"
+msgstr "Pořadí"
+
+msgid "Active for this session"
+msgstr "Aktivní v tomto sezení"
+
+msgid "Always active"
+msgstr "Stále aktivní"
+
+msgid "User directory"
+msgstr "Adresář uživatelů"
+
+msgid "Search a friend"
+msgstr "Najít kamaráda"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Požadovanou vlastnost nepodporuje buď příjemce nebo server, a proto nemůže být vykonána."
+
+msgid "This is a repeat from %s"
+msgstr "Jedná se o opakování od %s"
+
+msgid "Loading comments..."
+msgstr "Načítám komentáře..."
+
+msgid "Type your comment here..."
+msgstr "Napište svůj komentář zde ..."
+
+msgid "Could not get the comments!"
+msgstr "Nelze získat komentáře!"
+
+msgid "Show comments"
+msgstr "Zobrazit komentáře"
+
+msgid "Send him/her a message"
+msgstr "Odeslat jemu/jí zprávu"
+
+msgid "Start a chat with him/her"
+msgstr "Začít rozhovor s ním/ní"
+
+msgid "Media integration"
+msgstr "Integrovat media"
+
+msgid "Comments locked!"
+msgstr "Komentáře jsou uzamčené!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Zde napište, co si přejete sdílet s vašimi přáteli ..."
+
+msgid "changed his/her nickname to %s"
+msgstr "byla změněna jeho/její přezdívka na %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "pro komentování položky postupujte následovně: “%s”."
+
+msgid "Hide"
+msgstr "Skrýt"
+
+msgid "liked your post: “%s”."
+msgstr "váš oblíbený příspěvek: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "citoval jste někde: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "zvěřejněno na vaší nástěnce: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "jste označen na fotografii (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "jste označen na videu (%s)."
+
+msgid "Show"
+msgstr "Zobrazit"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Potřebujete pomoct? Raději si nejprve přečtete v dokumentaci stránku jak vyplnit tento formulář!"
+
+msgid "Pubsub host"
+msgstr "Pubsub hostitel"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix je velká sociální platforma, ke které máte přístup ať jste kdekoliv, kdykoliv chcete s někým komunikovat."
+
+msgid "Manager link"
+msgstr "Odkaz správce"
+
+msgid "User uploads server"
+msgstr "Uživate nahrávající na server"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Toto je uživatel nahrávající na server pro  %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Můžete si nastavit vlastní logo služby, které nahradí to výchozí. Dávejte při tom pozor na velikost a hlavní barvu každého loga!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Nahrát každé logo s doporučeným maximálním rozměrem v pixelech."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Toto není platný obrázek, použijte prosím PNG formát!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Vaše logo služby bylo úspěšně změněno!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Vaše logo musí být ve formátu PNG. Pokud je pole prázdné logo se nezmění."
+
+msgid "Remove this logo"
+msgstr "Odstranit toto logo"
+
+msgid "View this logo"
+msgstr "Zobrazit toto logo"
+
+msgid "Send a file"
+msgstr "Odeslat soubor"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Jakmile dojde k nahrání, bude váš kamarád vyzván ke stažení souboru, který jste odeslal."
+
+msgid "Groupchats to join"
+msgstr "Připojit skupinové rozhovory"
+
+msgid "Purge sent files"
+msgstr "Vyčistit odeslané soubory"
+
+msgid "would like to send you a file: “%s”."
+msgstr "přejete si odeslat soubor: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "souhlasí s přijetím souboru: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "odmítl přijmout soubor: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "nelze přijmout soubor: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "obdržel žádost pro výměnu souboru: “%s”."
+
+msgid "Available shortcuts:"
+msgstr "Dostupné klávesové zkratky:"
+
+msgid "%s removes the chat logs"
+msgstr "%s odstraní chat logy"
+
+msgid "%s joins a groupchat"
+msgstr "%s připojí skupinivý rozhovor"
+
+msgid "%s closes the chat"
+msgstr "%s uzavře rozhovor"
+
+msgid "%s shows the user profile"
+msgstr "%s zobrazí profil uživatele"
+
+msgid "%s sends a message to the room"
+msgstr "%s odešle zprávu do místnosti"
+
+msgid "%s changes your nickname"
+msgstr "%s změní vaší přezdívku"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s odešle zprávu  někomu v místnosti"
+
+msgid "%s changes the room topic"
+msgstr "%s změní téma místnosti"
+
+msgid "%s kicks an user of the room"
+msgstr "%s vykáže uživatele z místnosti"
+
+msgid "%s bans an user of the room"
+msgstr "%s zakáže uživateli přístup do místnosti"
+
+msgid "%s invites someone to join the room"
+msgstr "%s zve někoho do místnosti"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix je nezisková sociální platforma, ke které máte přístup ať jste kdekoliv, kdykoli budete chtít s někým komunikovat."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/de/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/de/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..e30d849
Binary files /dev/null and b/jappixmini/jappix/lang/de/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/de/LC_MESSAGES/main.po b/jappixmini/jappix/lang/de/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..75dba8f
--- /dev/null
@@ -0,0 +1,1870 @@
+# German translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:42+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Jappix benötigt JavaScript um zu funktionieren. Bitte erlaube die Ausführung von JavaScript."
+
+msgid "An open social network"
+msgstr "Ein offenes soziales Netzwerk"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix wurde von einem Netzwerkproblem, einem Programmfehler oder einer ungültigen Anmeldung unterbrochen. Bitte überprüfe, ob du deine Daten richtig eingegeben hast. Entschuldige die Störung."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Die Elementliste konnte nicht vom Server geladen werden."
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Dein Passwort wurde geändert. Du kannst dich jetzt mit deinen neuen Anmeldedaten anmelden."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Dein XMPP-Konto wurde entfernt."
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Du wurdest von Jappix abgemeldet."
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Der Chatraum, den du betreten hast, scheint nicht zu existieren. Du solltest ihn erstellen!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Der Chatraum wurde gelöscht. Jetzt kann ihn jemand anders registrieren."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Der Benutzer, den du erreichen möchtest, ist nicht in diesem Raum."
+
+msgid "Please enter the group chat address to join."
+msgstr "Gib die Adresse des Gruppenchats ein, um beizutreten."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Gib deinen Spitznamen ein, um %s beizutreten."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Dieser Raum (%s) ist passwortgeschützt."
+
+msgid "Your browser is out of date!"
+msgstr "Dein Browser ist veraltet!"
+
+msgid "Last %s version is better!"
+msgstr "Die letzte Version von %s ist besser!"
+
+msgid "Login"
+msgstr "Anmelden"
+
+msgid "Register"
+msgstr "Registrieren"
+
+msgid "Here we go!"
+msgstr "Los geht’s!"
+
+msgid "Server"
+msgstr "Anbieter"
+
+msgid "Password"
+msgstr "Passwort"
+
+msgid "Remember me"
+msgstr "Anmeldung merken"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Dieses Werkzeug wurde deaktiviert, du kannst es nicht verwenden."
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Aufgrund eines Netzwerkproblems wurde die Verbindung getrennt. Was möchtest du jetzt tun?"
+
+msgid "Reconnect"
+msgstr "Wiederverbinden"
+
+msgid "Messages"
+msgstr "Nachrichten"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Optionen"
+
+msgid "Disconnect"
+msgstr "Abmelden"
+
+msgid "Filter"
+msgstr "Filter"
+
+msgid "Add a friend"
+msgstr "Freund hinzufügen"
+
+msgid "Your groupchats"
+msgstr "Deine Gruppengespräche"
+
+msgid "Manage your favorite groupchats"
+msgstr "Verwalte deine Lieblings-Gruppenchats"
+
+msgid "More stuff"
+msgstr "Weitere Funktionen"
+
+msgid "Show all friends"
+msgstr "Alle Freunde anzeigen"
+
+msgid "Only show connected friends"
+msgstr "Nur verfügbare Freunde anzeigen"
+
+msgid "Message archives"
+msgstr "Nachrichtenarchiv"
+
+msgid "Date"
+msgstr "Datum"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Wähle einen Freund, um den Gesprächsverlauf anzusehen."
+
+msgid "Nothing found for: %s"
+msgstr "Nichts gefunden für: %s"
+
+msgid "A short message?"
+msgstr "Eine kurze Nachricht?"
+
+msgid "How are you?"
+msgstr "Wie geht es dir?"
+
+msgid "What are you doing?"
+msgstr "Was machst du gerade?"
+
+msgid "Join a chat"
+msgstr "Ein Gespräch betreten"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "Available"
+msgstr "Verfügbar"
+
+msgid "Talkative"
+msgstr "Gesprächig"
+
+msgid "Away"
+msgstr "Abwesend"
+
+msgid "Not available"
+msgstr "Nicht verfügbar"
+
+msgid "Busy"
+msgstr "Beschäftigt"
+
+msgid "Mood"
+msgstr "Laune"
+
+msgid "None"
+msgstr "Nichts"
+
+msgid "Crazy"
+msgstr "Verrückt"
+
+msgid "Excited"
+msgstr "Aufgeregt"
+
+msgid "Playful"
+msgstr "Verspielt"
+
+msgid "Happy"
+msgstr "Glücklich"
+
+msgid "Shocked"
+msgstr "Schockiert"
+
+msgid "Hot"
+msgstr "Heiß"
+
+msgid "Sad"
+msgstr "Traurig"
+
+msgid "Amorous"
+msgstr "Verliebt"
+
+msgid "Confident"
+msgstr "Zuversichtlich"
+
+msgid "Activity"
+msgstr "Aktivität"
+
+msgid "Chores"
+msgstr "Haushalt"
+
+msgid "Drinking"
+msgstr "Trinken"
+
+msgid "Eating"
+msgstr "Essen"
+
+msgid "Exercising"
+msgstr "Bewegung"
+
+msgid "Grooming"
+msgstr "Hygiene"
+
+msgid "Appointment"
+msgstr "Termin"
+
+msgid "Inactive"
+msgstr "Inaktiv"
+
+msgid "Relaxing"
+msgstr "Entspannt sich"
+
+msgid "Talking"
+msgstr "Unterhält sich"
+
+msgid "Traveling"
+msgstr "Auf Reise"
+
+msgid "Working"
+msgstr "Arbeiten"
+
+msgid "View profile"
+msgstr "Profil ansehen"
+
+msgid "Repeat this notice"
+msgstr "Wiederhole diese Nachricht"
+
+msgid "Remove this notice"
+msgstr "Entferne diese Nachricht"
+
+msgid "Your profile"
+msgstr "Dein Profil"
+
+msgid "Identity"
+msgstr "Identität"
+
+msgid "Profile image"
+msgstr "Profilbild"
+
+msgid "Others"
+msgstr "Andere"
+
+msgid "Personal"
+msgstr "Persönlich"
+
+msgid "Complete name"
+msgstr "Vollständiger Name"
+
+msgid "Nickname"
+msgstr "Spitzname"
+
+msgid "First name"
+msgstr "Vorname"
+
+msgid "Last name"
+msgstr "Nachname"
+
+msgid "Date of birth"
+msgstr "Geburtstag"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-Mail"
+
+msgid "Phone"
+msgstr "Telefon"
+
+msgid "Website"
+msgstr "Internetseite"
+
+msgid "Current"
+msgstr "Momentan"
+
+msgid "Delete"
+msgstr "Löschen"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Schade, du hast kein Profilbild angegeben."
+
+msgid "Address"
+msgstr "Adresse"
+
+msgid "Street"
+msgstr "Straße"
+
+msgid "City"
+msgstr "Stadt"
+
+msgid "Postal code"
+msgstr "Postleitzahl"
+
+msgid "Country"
+msgstr "Land"
+
+msgid "Biography"
+msgstr "Biografie"
+
+msgid "Important notice"
+msgstr "Wichtige Nachricht"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Sei vorsichtig mit Informationen, die du in dein Profil schreibst. Diese Infos können von allen gelesen werden."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Nicht alles ist privat bei XMPP. Das hier ist eines davon: dein öffentliches Profil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Es wird empfohlen ein Profilbild hochzuladen (maximal %s), z.b. ein Bild von dir damit deine Freunde dich leichter wieder erkennen können."
+
+msgid "Save"
+msgstr "Speichern"
+
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgid "Edit options"
+msgstr "Eigenschaften bearbeiten"
+
+msgid "Channel"
+msgstr "Kanal"
+
+msgid "Commands"
+msgstr "Befehle"
+
+msgid "Sounds"
+msgstr "Geräusche"
+
+msgid "Privacy"
+msgstr "Privatsphäre"
+
+msgid "Message archiving"
+msgstr "Nachrichtenarchivierung"
+
+msgid "Store a history of your chats"
+msgstr "Speichere einen Verlauf deiner Gespräche"
+
+msgid "Geolocation"
+msgstr "Geodaten"
+
+msgid "Empty"
+msgstr "Leer"
+
+msgid "Empty channel"
+msgstr "Leerer Kanal"
+
+msgid "Persistent"
+msgstr "Dauerhaft"
+
+msgid "Maximum notices"
+msgstr "Maximale Benachrichtigungen"
+
+msgid "Account"
+msgstr "Account"
+
+msgid "Change password"
+msgstr "Passwort ändern"
+
+msgid "Delete account"
+msgstr "Konto löschen"
+
+msgid "Old"
+msgstr "Alt"
+
+msgid "New (2 times)"
+msgstr "Neu (zwei Mal)"
+
+msgid "Continue"
+msgstr "Fortsetzen"
+
+msgid "To"
+msgstr "An"
+
+msgid "Close"
+msgstr "Schließen"
+
+msgid "unknown"
+msgstr "Unbekannt"
+
+msgid "Unavailable"
+msgstr "Nicht erreichbar"
+
+msgid "is now"
+msgstr "ist jetzt"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Bitte warte während dein Avatar hochgeladen wird..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Hier ist es! Ein wunderschönes, neues Profilbild."
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Die Bilddatei hat ein falsches Format oder ist zu groß."
+
+msgid "Reply"
+msgstr "Antworten"
+
+msgid "Error"
+msgstr "Fehler"
+
+msgid "Click here to solve the error"
+msgstr "Klicke hier, um den Fehler zu beheben"
+
+msgid "You"
+msgstr "Du"
+
+msgid "Remove"
+msgstr "Entfernen"
+
+msgid "Rename"
+msgstr "Umbenennen"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Hey, ich bin %s. Ich möchte dich gerne als Freund hinzufügen."
+
+msgid "Smiley insertion"
+msgstr "Smilie einfügen"
+
+msgid "Change style"
+msgstr "Stil ändern"
+
+msgid "Text in bold"
+msgstr "Text fett"
+
+msgid "Text in italic"
+msgstr "Text kursiv"
+
+msgid "Underlined text"
+msgstr "Text unterstrichen"
+
+msgid "Save chat"
+msgstr "Protokoll speichern"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Klicke auf den folgenden Link, um das Chatprotokoll zu erhalten. Warte ein bisschen und klicke noch Mal, um die Datei zu bekommen."
+
+msgid "This chat is empty!"
+msgstr "Dieses Gespräch ist leer."
+
+msgid "Generate file!"
+msgstr "Datei generieren!"
+
+msgid "Download file!"
+msgstr "Datei herunterladen!"
+
+msgid "Clean current chat"
+msgstr "Aktuelles Gespräch leeren"
+
+msgid "View chat history"
+msgstr "Gesprächsverlauf anzeigen"
+
+msgid "Show user profile"
+msgstr "Nutzerprofil zeigen"
+
+msgid "Add this contact to your friends"
+msgstr "Kontakt zu Freunden hinzufügen"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Gruppengespräch zu Favoriten hinzufügen"
+
+msgid "All tabs"
+msgstr "Alle Tabs"
+
+msgid "Close this tab"
+msgstr "Diesen Tab schließen"
+
+msgid "no subject defined for this room."
+msgstr "Für diesen Raum ist kein Thema festgelegt."
+
+msgid "Administration panel for this room"
+msgstr "Verwaltung für diesen Raum"
+
+msgid "Moderators"
+msgstr "Moderatoren"
+
+msgid "Participants"
+msgstr "Teilnehmer"
+
+msgid "Visitors"
+msgstr "Besucher"
+
+msgid "Manage favorite rooms"
+msgstr "Favorisierte Räume verwalten"
+
+msgid "Change favorites"
+msgstr "Favoriten ändern"
+
+msgid "Search a room"
+msgstr "Raum suchen"
+
+msgid "Select a favorite"
+msgstr "Einen Favoriten wählen"
+
+msgid "Getting the name..."
+msgstr "Name wird geladen …"
+
+msgid "Gateway"
+msgstr "Gateway"
+
+msgid "Name"
+msgstr "Name"
+
+msgid "Room"
+msgstr "Raum"
+
+msgid "Add"
+msgstr "Hinzufügen"
+
+msgid "Edit"
+msgstr "Bearbeiten"
+
+msgid "Search a room on"
+msgstr "Einen Raum suchen in "
+
+msgid "No room found on this server."
+msgstr "Auf diesem Server wurden keine Räume gefunden."
+
+msgid "Service discovery"
+msgstr "Übersicht der Dienste"
+
+msgid "Server to query"
+msgstr "Server zur Abfrage"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Es wurde kein Ergebnis gefunden."
+
+msgid "Accounts"
+msgstr "Konten"
+
+msgid "Authentications"
+msgstr "Genehmigung"
+
+msgid "Automation"
+msgstr "Automatisierung"
+
+msgid "Clients"
+msgstr "Klienten"
+
+msgid "Collaboration"
+msgstr "Zusammenarbeit"
+
+msgid "Components"
+msgstr "Komponenten"
+
+msgid "Rooms"
+msgstr "Räume"
+
+msgid "Directories"
+msgstr "Verzeichnisse"
+
+msgid "Gateways"
+msgstr "Gateways"
+
+msgid "News"
+msgstr "Neuigkeiten"
+
+msgid "Hierarchy"
+msgstr "Hierarchie"
+
+msgid "Proxies"
+msgstr "Proxys"
+
+msgid "Publication/Subscription"
+msgstr "Veröffentlichung / Abonnement"
+
+msgid "Storage"
+msgstr "Speicher"
+
+msgid "Service offline or broken"
+msgstr "Service offline oder abgestürzt"
+
+msgid "Your inbox"
+msgstr "Posteingang"
+
+msgid "Available actions"
+msgstr "Verfügbare Aktionen"
+
+msgid "Clean"
+msgstr "Säubern"
+
+msgid "New"
+msgstr "Neu"
+
+msgid "Received"
+msgstr "Erhalten"
+
+msgid "Subject"
+msgstr "Betreff"
+
+msgid "Content"
+msgstr "Inhalt"
+
+msgid "Send message"
+msgstr "Nachricht schicken"
+
+msgid "Your inbox is empty."
+msgstr "Dein Posteingang ist leer."
+
+msgid "MUC administration"
+msgstr "MUC-Administration"
+
+msgid "You administrate this room"
+msgstr "Du verwaltest diesen Raum."
+
+msgid "Enter new subject"
+msgstr "Neuer Betreff"
+
+msgid "Configuration"
+msgstr "Einstellungen"
+
+msgid "Authorizations"
+msgstr "Genehmigung"
+
+msgid "Member list"
+msgstr "Mitgliederliste"
+
+msgid "Owner list"
+msgstr "Besitzerliste"
+
+msgid "Administrator list"
+msgstr "Verwalterliste"
+
+msgid "Outcast list"
+msgstr "Gebannten-Liste"
+
+msgid "Add an input"
+msgstr "Eingabe hinzufügen"
+
+msgid "Destroy this MUC"
+msgstr "Diesen MUC schließen"
+
+msgid "Yes, let's do it!"
+msgstr "Ja, los geht's!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Dein Freund tippt."
+
+msgid "Your friend is writing a message..."
+msgstr "Dein Freund schreibt eine Nachricht."
+
+msgid "Your friend stopped writing a message."
+msgstr "Dein Freund hat aufgehört, eine Nachricht zu schreiben."
+
+msgid "Your friend is doing something else."
+msgstr "Dein Freund tut etwas anderes."
+
+msgid "Your friend closed the chat."
+msgstr "Dein Freund hat die Unterhaltung beendet."
+
+msgid "Requesting this service..."
+msgstr "Dienst wird angefordert …"
+
+msgid "Loading"
+msgstr "Lädt …"
+
+msgid "joined the chat room"
+msgstr "hat den Raum betreten"
+
+msgid "left the chat room"
+msgstr "hat den Raum verlassen"
+
+msgid "no status"
+msgstr "kein Status"
+
+msgid "has been kicked"
+msgstr "wurde rausgeschmissen."
+
+msgid "has been banned"
+msgstr "wurde verbannt."
+
+msgid "no reason"
+msgstr "kein Grund"
+
+msgid "Communicate with the entire world!"
+msgstr "Kommuniziere mit der ganzen Welt!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Du kannst Kontakt aufnehmen mit den Millionen von Nutzern des XMPP-Netzwerkes. Tritt der Gemeinschaft bei und bleib frei!"
+
+msgid "Hi there!"
+msgstr "Hallo du!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Willkommen bei %1s, »%2s«."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Melde dich mit deinem bestehenden XMPP-Konto an oder erstelle gratis ein Neues!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix ist ein quelloffenes Projekt von PostPro, einer gemeinnützigen Organisation die uns großartig unterstützt."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Melde dich mit deinem XMPP-Konto an. Du kannst auch %s benutzen, um einem Gruppenchat beizutreten."
+
+msgid "Previous"
+msgstr "Vorhergehend"
+
+msgid "General"
+msgstr "Allgemeines"
+
+msgid "Advanced"
+msgstr "Erweitert"
+
+msgid "Resource"
+msgstr "Ressource"
+
+msgid "Priority"
+msgstr "Priorität"
+
+msgid "Low"
+msgstr "Niedrig"
+
+msgid "Medium"
+msgstr "Mittel"
+
+msgid "High"
+msgstr "Hoch"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Nenne den Chat, dem du beitreten willst und das Pseudonym, das du haben willst. Du kannst auch zurück zu %s."
+
+msgid "login page"
+msgstr "Anmeldeseite"
+
+msgid "Share this link with your friends:"
+msgstr "Teile diesen Verweis mit deinen Freunden:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Registriere ein neues XMPP-Konto, um mit deinen Freunden dein eigenes soziales Netz zu bilden. Es ist so einfach!"
+
+msgid "Required"
+msgstr "Notwendig"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Du wurdest registriert, deine XMPP-Adresse lautet:"
+
+msgid "Manager"
+msgstr "Verwalter"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Verschlüsselt"
+
+msgid "Unencrypted"
+msgstr "Unverschlüsselt"
+
+msgid "Where are you?"
+msgstr "Wo bist du?"
+
+msgid "What's up with you?"
+msgstr "Was gibt’s?"
+
+msgid "Fetching the social channel..."
+msgstr "Sozialer Kanal wird abgerufen …"
+
+msgid "You are synchronized with your network."
+msgstr "Du bist mit deinen Netzwerken abgeglichen."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Nichts kann gesendet werden: Du kannst nur Nachrichten empfangen!"
+
+msgid "Media viewer"
+msgstr "Medienbibliothek"
+
+msgid "Browse"
+msgstr "Durchblättern"
+
+msgid "Command"
+msgstr "Befehl"
+
+msgid "Subscribe"
+msgstr "Abonnieren"
+
+msgid "Join"
+msgstr "Beitreten"
+
+msgid "Automatic"
+msgstr "Automatisch"
+
+msgid "Search"
+msgstr "Suchen"
+
+msgid "No result!"
+msgstr "Kein Ergebnis!"
+
+msgid "No notifications."
+msgstr "Keine Benachrichtigungen."
+
+msgid "would like to add you as a friend."
+msgstr "würde dich gerne als Freund hinzufügen."
+
+msgid "would like you to join this chatroom:"
+msgstr "würde gerne diesen Chatraum betreten."
+
+msgid "Do you accept?"
+msgstr "Akzeptieren?"
+
+msgid "Yes"
+msgstr "Ja"
+
+msgid "No"
+msgstr "Nein"
+
+msgid "would like to get authorization."
+msgstr "möchte bestätigt werden."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Möchtest du die Freunde sehen, die %s dir empfiehlt?"
+
+msgid "Submit"
+msgstr "Senden"
+
+msgid "Client"
+msgstr "Client"
+
+msgid "System"
+msgstr "System"
+
+msgid "Local time"
+msgstr "Lokale Zeit"
+
+msgid "Comments"
+msgstr "Kommentare"
+
+msgid "User profile"
+msgstr "Benutzerprofil"
+
+msgid "See his/her position on the globe"
+msgstr "Position auf der Welt"
+
+msgid "Confirm"
+msgstr "Bestätigen"
+
+msgid "anonymous mode"
+msgstr "Anonymer Modus"
+
+msgid "Groups"
+msgstr "Gruppen"
+
+msgid "Unclassified"
+msgstr "Nicht eingeordnet"
+
+msgid "Authorize"
+msgstr "Genehmigen"
+
+msgid "Ask for authorization"
+msgstr "Frage nach Genehmigung"
+
+msgid "Unblock"
+msgstr "Freischalten"
+
+msgid "Prohibit"
+msgstr "Verbieten"
+
+msgid "Block"
+msgstr "Blockieren"
+
+msgid "Chat"
+msgstr "Chat"
+
+msgid "Groupchat"
+msgstr "Gruppenchat"
+
+msgid "Jappix Mobile"
+msgstr "Jappix unterwegs"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Unterwegs"
+
+msgid "Please wait..."
+msgstr "Bitte warten …"
+
+msgid "Please enable JavaScript"
+msgstr "Bitte JavaScript aktivieren"
+
+msgid "Your channel"
+msgstr "Dein Kanal"
+
+msgid "Channel of"
+msgstr "Kanal von"
+
+msgid "More notices..."
+msgstr "Mehr Nachrichten …"
+
+msgid "Attach a file"
+msgstr "Datei anhängen"
+
+msgid "Send"
+msgstr "Senden"
+
+msgid "Unattach the file"
+msgstr "Angehängte Datei löschen"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Beim Hochladen deiner Datei ist ein Fehler aufgetreten: Wahrscheinlich ist es zu groß (maximal %s) oder verboten!"
+
+msgid "Authorization failed"
+msgstr "Genehmigung fehlgeschlagen"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrierung fehlgeschlagen. Bitte wähle einen anderen Benutzernamen."
+
+msgid "Service unavailable"
+msgstr "Dienst nicht erreichbar"
+
+msgid "Internal server error, try later"
+msgstr "Interner Serverfehler. Versuche es später noch Mal."
+
+msgid "Your form has been sent."
+msgstr "Das Formular wurde versendet."
+
+msgid "Application"
+msgstr "Anwendung"
+
+msgid "XMPP links"
+msgstr "XMPP-Verweise"
+
+msgid "Open XMPP links with Jappix"
+msgstr "XMPP-Verweise mit Jappix öffnen"
+
+msgid "changed the subject to:"
+msgstr "hat das Thema geändert zu:"
+
+msgid "Welcome!"
+msgstr "Willkommen!"
+
+msgid "Friends"
+msgstr "Freunde"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Willkommen bei Jappix!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Bevor du beginnst, musst du noch einiges einstellen, nach Freunden suchen und dein Profil ausfüllen."
+
+msgid "Enable notification sounds"
+msgstr "Benachrichtigungsgeräusche einschalten"
+
+msgid "Share your position on the globe"
+msgstr "Deine Position freigeben"
+
+msgid "Offline friends"
+msgstr "Freunde (nicht verfügbar)"
+
+msgid "Don't hide offline friends"
+msgstr "Nicht verfügbare Freunde anzeigen"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Benutze dieses Werkzeug, um Freunde auf dem aktuellen Server zu finden, oder versuche es später."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Gut gemacht! Jetzt kannst du Jappix mit deinen Freunden teilen!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Wenn du Speichern klickst, wird die Profilbearbeitung geöffnet. Fröhliches Netzwerken!"
+
+msgid "Share Jappix on %s"
+msgstr "Jappix über %s teilen"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Ich nutze Jappix, ein freies soziales Netzwerk. Ich bin %s!"
+
+msgid "Unknown name"
+msgstr "Unbekannter Name"
+
+msgid "Unknown country"
+msgstr "Unbekanntes Land"
+
+msgid "Click to enable"
+msgstr "Zum Einschalten klicken"
+
+msgid "Click to disable"
+msgstr "Zum Ausschalten klicken"
+
+msgid "Installation"
+msgstr "Installation"
+
+msgid "Jappix installation"
+msgstr "Jappix-Installation"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Willkommen zur Jappix-Installation"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Dieses Tool wird dir helfen Jappix, die erste voll funktionstüchtige XMPP-basierte soziale Platform, schnell auf deinem Server zu installieren. Du brauchst dazu nichteinmal technisches Wissen."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Lass uns die Installationsschritte durchgehen."
+
+msgid "Welcome"
+msgstr "Willkommen"
+
+msgid "Storage configuration"
+msgstr "Speicher-Konfiguration"
+
+msgid "Administrator account"
+msgstr "Verwalter-Konto"
+
+msgid "Main configuration"
+msgstr "Haupteinstellungen"
+
+msgid "Hosts configuration"
+msgstr "Host-Einstellungen"
+
+msgid "Services installation"
+msgstr "Installation von Diensten"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Wenn die derzeitige Sprache nicht deine ist (%1s), kann Jappix deine sprechen %2s dies wird gespeichert werden."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Wenn du Hilfe bei der Jappix-Installation und -Konfiguration benötigst, kannst du unsere ganze Dokumentation verwenden:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Es ist Zeit dein eigenes soziales Netzt zu bauen: Gehe zum nächsten Schritt!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix speichert permanente Dateien (wie öffentliche Dateien, Chatlogs, deine Musik und die Einstellungen) in einem separat gesicherten Ordner."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix muss Schreibberechtigungen in diesem Ordner haben um sein Unterordner zu erzeugen. Wenn nicht, setze die Rechte zu %1s oder ändere den Besitzer des Ordners zu %2s, je nach deiner Konfiguration."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Der Ordner ist schreibbar, du kannst weitermachen!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix bietet dir die Möglichkeit, deine Konfiguration einzustellen, neue Plugins zu installieren oder nach Updates zu suchen. Deshalb musst Du ein Admin-Account anlegen um auf die Verwaltung zugreifen zu können."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Wenn Jappix installiert ist, klicke einfach auf den Manager-Link auf der Homepage um darauf zuzugreifen."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Du hast etwas vergessen, oder die beiden Passwörter stimmen nicht überein."
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix benötigt einige Werte um richtig zum Funktionieren. Bitte ändere die folgenden Eingaben (oder behalte die Vorgaben, welche für die meisten Leute passen)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Beachte, wenn ein obligatorischer Wert nicht gesetzt wird, so wird dieser automatisch mit dem vorgegebenen ersetzt. "
+
+msgid "User"
+msgstr "Benutzer"
+
+msgid "Service"
+msgstr "Dienst"
+
+msgid "Service name"
+msgstr "Name des Dienstes"
+
+msgid "Service description"
+msgstr "Dienst-Beschreibung"
+
+msgid "Connection"
+msgstr "Verbindung"
+
+msgid "Lock the host"
+msgstr "Sperre den Host"
+
+msgid "Anonymous mode"
+msgstr "Anonymer Modus"
+
+msgid "Registration allowed"
+msgstr "Registrieren erlaubt"
+
+msgid "Use a proxy"
+msgstr "Einen Proxy nutzen"
+
+msgid "Encryption"
+msgstr "Verschlüsselung"
+
+msgid "HTTPS storage"
+msgstr "HTTPS-Speicher"
+
+msgid "Force HTTPS"
+msgstr "Sichere Verbindung erzwingen"
+
+msgid "Compression"
+msgstr "Komprimierung"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Diese Seite hilft dir Jappix' Default-Hosts zu spezifizieren. Du kannst alles lassen wie es ist, wenn du den offiziellen Service-Host nutzen willst."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Vielleicht weißt du nicht, was ein BOSH-Server ist? Es ist ein Verbindung zwischen dem Jappix-Client und einem XMPP-Server, welcher aufgrund technischer Beschränkungen nötig ist."
+
+msgid "Main host"
+msgstr "Haupt-Host"
+
+msgid "Groupchat host"
+msgstr "Gruppenchat-Host"
+
+msgid "Anonymous host"
+msgstr "Anonymer Host"
+
+msgid "Directory host"
+msgstr "Verzeichnis-Host"
+
+msgid "BOSH host"
+msgstr "BOSH-Host"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Du kannst einige extra Software auf deinem Server installieren um Jappix Funktionen zu erweitern. Manche müssen vielleicht aufgrund von Sicherheitsbeschränkungen modifiziert werden."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Um dies durchzuführen, musst du Zugriff auf Konsole des Servers mit Root-Rechten haben. Dies ist fakultativ. Jappix wird ohne die Module funktionieren, aber einige Features werden nicht verfügbar sein."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Nach dem Ende der Installation wird Jappix die Cache-Files erzeugen. Dies kann etwas dauern. Bitte warte, bis die Anwendung angezeigt wird und drücke keine währenddessen keine Taste."
+
+msgid "Thanks for using Jappix!"
+msgstr "Vielen Dank für die Benutzung von Jappix!"
+
+msgid "Next"
+msgstr "Weiter"
+
+msgid "Finish"
+msgstr "Beenden"
+
+msgid "Check again"
+msgstr "Nochmals überprüfen"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Der Ordner ist nicht beschreibbar. Setze die korrekten Berechtigungen für den Ordner %s"
+
+msgid "%s is installed on your system."
+msgstr "%s ist auf deinem System installiert."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s ist nicht auf denem System installiert, du solltest %2s installieren."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "Die maximale Größe für PHP-Uploads reicht aus (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "Die maximale Größe für PHP-Uploads reicht nicht aus (%1s), du solltest es für %2s in %3s bestimmen."
+
+msgid "Jappix manager"
+msgstr "Jappix-Verwaltung"
+
+msgid "Manager access"
+msgstr "Verwalter-Zugang"
+
+msgid "Statistics"
+msgstr "Statistiken"
+
+msgid "Hosts"
+msgstr "Hosts"
+
+msgid "Design"
+msgstr "Gestaltung"
+
+msgid "Repeat"
+msgstr "Wiederholen"
+
+msgid "All"
+msgstr "Alle"
+
+msgid "Horizontal"
+msgstr "Horizontal"
+
+msgid "Vertical"
+msgstr "Vertikal"
+
+msgid "Center"
+msgstr "Zentriert"
+
+msgid "Left"
+msgstr "Links"
+
+msgid "Right"
+msgstr "Rechts"
+
+msgid "Top"
+msgstr "Oben"
+
+msgid "Bottom"
+msgstr "Unten"
+
+msgid "Adapt"
+msgstr "Anpassen"
+
+msgid "Color"
+msgstr "Farbe"
+
+msgid "Users"
+msgstr "Benutzer"
+
+msgid "Updates"
+msgstr "Aktualisierungen"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Dies ist ein eingeschränkter Bereich: Nur genehmigte Benutzer können diese Jappix-Node verwalten."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Benutze das Formular für die Anmeldung in den Verwaltungsbereich."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Zur Sicherheit sind Sitzungen zeitbegrenzt. Wenn du den Browser schließt, wirst du ebenfalls abgemeldet."
+
+msgid "Credentials"
+msgstr "Anmeldedaten"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Du wurdest abgemeldet. Auf Wiedersehen!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Du konntest nicht als Verwalter erkannt werden. Bitte prüfe deine Eingabe."
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Grundsätzliche Statistiken einiger wichtiger Dinge werden von Jappix erfasst. Du findest sie untenstehend."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Ändere die Jappix Node-Konfiguration mit diesem Tool."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Ändere den XMPP-Hosts den dieser Jappix-Node nutzt mit diesem Tool."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Alle Datein dieses Jappix-Nodes können mit diesem Tool verwaltet werden: Bitte wähle ein Unterverzeichnis und editiere dessen Inhalt."
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix ist voll anpassbar: Du kannst sein Design hier ändern."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Ungültiges Bildformat! Benutze bitte PNG, GIF oder JPEG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Das Bild konnte nicht übertragen werden. Bitte versuche es noch Mal."
+
+msgid "Your image was added to the list!"
+msgstr "Dein Bild wurde hinzugefügt!"
+
+msgid "Changes saved!"
+msgstr "Änderungen gespeichert!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Du kannst mehr als einen Administrator für diesen Jappix-Node festlegen. Du kannst mit diesem Tool auch ein Password ändern."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Aktualisiere deinen Jappix-Node mit diesem Tool, oder schau nach, ob ein neues verfügbar ist. Informationen über die neuste Version werden auch (in englisch) angezeigt."
+
+msgid "Access statistics"
+msgstr "Zugriffs-Statistiken"
+
+msgid "Share statistics"
+msgstr "Freigabe-Statistiken"
+
+msgid "Other statistics"
+msgstr "Andere Statistiken"
+
+msgid "January"
+msgstr "Januar"
+
+msgid "February"
+msgstr "Februar"
+
+msgid "March"
+msgstr "März"
+
+msgid "April"
+msgstr "April"
+
+msgid "May"
+msgstr "Mai"
+
+msgid "June"
+msgstr "Juni"
+
+msgid "July"
+msgstr "Juli"
+
+msgid "August"
+msgstr "August"
+
+msgid "September"
+msgstr "September"
+
+msgid "October"
+msgstr "Oktober"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "Dezember"
+
+msgid "Monday"
+msgstr "Montag"
+
+msgid "Tuesday"
+msgstr "Dienstag"
+
+msgid "Wednesday"
+msgstr "Mittwoch"
+
+msgid "Thursday"
+msgstr "Donnerstag"
+
+msgid "Friday"
+msgstr "Freitag"
+
+msgid "Saturday"
+msgstr "Samstag"
+
+msgid "Sunday"
+msgstr "Sonntag"
+
+msgid "Total"
+msgstr "Gesamt"
+
+msgid "Cache"
+msgstr "Zwischenspeicher"
+
+msgid "Logs"
+msgstr "Protokolle"
+
+msgid "Music"
+msgstr "Musik"
+
+msgid "Backgrounds"
+msgstr "Hintergründe"
+
+msgid "Share"
+msgstr "Freigabe"
+
+msgid "Background"
+msgstr "Hintergrund"
+
+msgid "Notice"
+msgstr "Hinweis"
+
+msgid "Your design preferences have been saved!"
+msgstr "Deine Gestaltung wurde gespeichert."
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Bitte kontrolliere deine Eingaben: Es fehlt etwas!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Ändere Dein Jappix-Node Hintergrund mit diesem Tool. Du kannst entweder eine eigene Farbe oder ein hochgeladenes Bild wählen. Sei kreativ!"
+
+msgid "Use default background"
+msgstr "Vorgegebenen Hintergrund verwenden"
+
+msgid "Use your own image"
+msgstr "Bild selber wählen"
+
+msgid "Select a background to use and change the display options."
+msgstr "Einen Hintergrund wählen und die Gestaltung ändern."
+
+msgid "Use your own color"
+msgstr "Farbe selber wählen"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Der hexadezimale Farbwert für den Hintergrund."
+
+msgid "Manage backgrounds"
+msgstr "Hintergründe verwalten"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Du kannst einen neuen Hintergrund hinzufügen. Bitte sende ein gültiges Bild."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Wenn du einen Hintergrund entfernen möchtest, benutze den untenstehenden Browser."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Einen Hinweis auf der Startseite für all deine Besucher erstellen."
+
+msgid "Simple notice"
+msgstr "Einfacher Hinweis"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Diesen Hinweis kannst du mit normalem Text nutzen, Code ist nicht erlaubt!"
+
+msgid "Advanced notice"
+msgstr "Erweiterter Hinweis"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Du kannst deine Ankündigung mit HTML, CSS und JavaScript bearbeiten. Aber du musst den Code selbst erstellen."
+
+msgid "Available updates"
+msgstr "Verfügbare Aktualisierungen"
+
+msgid "What's new?"
+msgstr "Was gibt’s Neues?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Deine Speicherordner haben keine Schreibrechte, bitte ändere das!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s kann Probleme mit dem Proxy verursachen. Bitte erhöhe den Wert von %2s auf %3s."
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Du benutzt eine Entwicklerversion von Jappix. Du kannst über unser Repository Updates beziehen wenn du %s ausführst."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Eine neue Version von Jappix ist verfügbar! Schau’ dir die Neuerungen an und starte die Aktualisierung!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Deine Version ist veraltet. Klicke hier, um auf %2 zu aktualisieren."
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Deine Version schein aktuell zu sein, aber du kannst es manuell prüfen, indem du hier klickst."
+
+msgid "Check for updates"
+msgstr "Nach Updates suchen"
+
+msgid "Update in progress"
+msgstr "Wird aktualisiert"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix wurde aktualisiert: Du benutzt nun die neueste Version. Viel Spaß!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Die Aktualisierung schlug fehl! Bitte versuche es später noch ein Mal."
+
+msgid "Downloading package..."
+msgstr "Wird heruntergeladen …"
+
+msgid "Removing current Jappix system files..."
+msgstr "Aktuelle Jappix-Systemdateien werden entfernt …"
+
+msgid "Extracting package..."
+msgstr "Wird entpackt …"
+
+msgid "Regenerating storage folder tree..."
+msgstr "Verzeichnisbaum wird neu erstellt …"
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix ist jetzt aktuell!"
+
+msgid "Aborted: socket error!"
+msgstr "Abbruch: Socket-Fehler!"
+
+msgid "Aborted: buffer error!"
+msgstr "Abbruch: Puffer-Fehler!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Abbruch: Keine Schreibrechte!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Abbruch: Paket konnte nicht entpackt werden!"
+
+msgid "Visits"
+msgstr "Besuche"
+
+msgid "Daily"
+msgstr "Täglich"
+
+msgid "Weekly"
+msgstr "Wöchentlich"
+
+msgid "Monthly"
+msgstr "Monatlich"
+
+msgid "Yearly"
+msgstr "Jährlich"
+
+msgid "Size"
+msgstr "Größe"
+
+msgid "Clean everything"
+msgstr "Alles säubern"
+
+msgid "Purge cache"
+msgstr "Cache leeren"
+
+msgid "Purge logs"
+msgstr "Protokolle löschen"
+
+msgid "Purge updates"
+msgstr "Aktualisierungen löschen"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Das Speicher-Verzeichnis, das du säubern wolltest ist jetzt leer!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Halte deinen Jappix-Node frisch und schnell, säubere die Speicher-Ordner regelmäßig!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Lade deine Musik (Ogg Vorbis, MP3 oder WAV) hoch um sie in Jappix zu hören."
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Die hochzuladende Datei muss kleiner als %s sein."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Bleib auf dem Laufenden, was Deine Nutzer auf deinem Server speichern und entferne ungewünschte Inhalte mit diesem Tool."
+
+msgid "Title"
+msgstr "Titel"
+
+msgid "Artist"
+msgstr "Künstler"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Datei"
+
+msgid "Upload"
+msgstr "Hochladen"
+
+msgid "The folder is empty."
+msgstr "Dieser Ordner ist leer."
+
+msgid "The music could not be received, please retry!"
+msgstr "Deine Musik konnte nicht empfangen werden, bitte versuche es noch ein Mal."
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Das ist keine gültige Musikdatei, bitte nimm eine Ogg Vorbis, MP3 oder WAV!"
+
+msgid "Your music has been added!"
+msgstr "Deine Musik wurde hinzugefügt."
+
+msgid "The selected elements have been removed."
+msgstr "Die ausgewählten Elemente wurden entfernt."
+
+msgid "You must select elements to remove!"
+msgstr "Sie müssen Elemente auswählen um welche zu entfernen!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Füge neue Beutzer mit diesem Tool hinzu. Ändere ein Passwort (gebe einen existierenden Benutzernamen ein). Bitte benutze ein starkes Passwort!"
+
+msgid "Manage"
+msgstr "Verwalten"
+
+msgid "List"
+msgstr "Liste"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Entferne Benutzer mit diesem Tool. Beachte, dass du keinen Benutzer entfernen kannst, wenn er der einzig exisierende ist."
+
+msgid "The user has been added!"
+msgstr "Der Benutzer wurde hinzugefügt."
+
+msgid "The chosen users have been removed."
+msgstr "Die ausgewählten Benutzer wurden entfernt."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Du musst einen oder mehrere Benutzer auswählen, die gelöscht werden sollen!"
+
+msgid "Yesterday"
+msgstr "Gestern"
+
+msgid "%s days ago"
+msgstr "Vor %s Tagen"
+
+msgid "User currently active"
+msgstr "Benutzer momentan aktiv"
+
+msgid "Last seen: %s"
+msgstr "Zuletzt gesehen: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inaktiv seit: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Dein Freund hat deine Nachricht anscheinend nicht erhalten!"
+
+msgid "Static content server"
+msgstr "Statischer Inhaltsserver"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Dies ist der statische Inhaltsserver für %1s, »%2s«."
+
+msgid "Suggested friends"
+msgstr "Empfohlene Freunde"
+
+msgid "Check all"
+msgstr "Alle auswählen"
+
+msgid "Uncheck all"
+msgstr "Alle abwählen"
+
+msgid "Choose"
+msgstr "Wählen"
+
+msgid "List name"
+msgstr "Listenname"
+
+msgid "Allow"
+msgstr "Erlauben"
+
+msgid "Deny"
+msgstr "Ablehnen"
+
+msgid "Group"
+msgstr "Gruppe"
+
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgid "Both"
+msgstr "Beides"
+
+msgid "From"
+msgstr "Von"
+
+msgid "Everybody"
+msgstr "Jeder"
+
+msgid "Send messages"
+msgstr "Nachrichten senden"
+
+msgid "Send queries"
+msgstr "Anfragen senden"
+
+msgid "See my status"
+msgstr "Status einsehen"
+
+msgid "Send his/her status"
+msgstr "Status senden"
+
+msgid "Everything"
+msgstr "Alles"
+
+msgid "Item"
+msgstr "Element"
+
+msgid "Order"
+msgstr "Reihenfolge"
+
+msgid "Active for this session"
+msgstr "Aktiv in dieser Sitzung"
+
+msgid "Always active"
+msgstr "Immer aktiv"
+
+msgid "User directory"
+msgstr "Nutzerverzeichnis"
+
+msgid "Search a friend"
+msgstr "Einen Freund suchen"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Die anfegorderte Funktion ist beim Server oder Empfänger nicht implementiert und kann daher nicht ausgeführt werden."
+
+msgid "This is a repeat from %s"
+msgstr "Dies ist eine Wiederholung von %s"
+
+msgid "Loading comments..."
+msgstr "Lade Kommentare..."
+
+msgid "Type your comment here..."
+msgstr "Gebe dein Kommentar hier ein..."
+
+msgid "Could not get the comments!"
+msgstr "Konnte Kommentare nicht laden!"
+
+msgid "Show comments"
+msgstr "Zeige Kommentare"
+
+msgid "Send him/her a message"
+msgstr "Sende Ihm/Ihr eine Nachricht"
+
+msgid "Start a chat with him/her"
+msgstr "Starte Chat mit Ihm/Ihr"
+
+msgid "Media integration"
+msgstr "Medien Einbindung"
+
+msgid "Comments locked!"
+msgstr "Kommentare sind gesperrt!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Schreibe etwas, um es mit deinen Freunden zu teilen..."
+
+msgid "changed his/her nickname to %s"
+msgstr "hat Seinen Spitznamen zu %s geändert"
+
+msgid "commented an item you follow: “%s”."
+msgstr "hat ein Item, dem du folgst, kommentiert: »%s«."
+
+msgid "Hide"
+msgstr "Verstecken"
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr "hat dich zitiert: »%s«."
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr "hat dich in einem Foto markiert (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "hat dich in einem Video markiert (%s)."
+
+msgid "Show"
+msgstr "Zeigen"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Brauchst du Hilfe? Lies unsere Dokumentation, wie man dieses Formular ausfüllt!"
+
+msgid "Pubsub host"
+msgstr "Pubsub Anbieter"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix ist eine großartige soziale Platform, auf die du immer und überall Zugriff hast und auf der du kommunizieren kannst, mit wem du willst."
+
+msgid "Manager link"
+msgstr "Manager Link"
+
+msgid "User uploads server"
+msgstr "Nutzer-Uploadserver"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Dies ist der Nutzer-Uploadserver für %1s, »%2s«."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Du kannst dein eigenes Service-Logo setzen, um das Standard-Logo zu ersetzen. Pass auf die Größe und Hauptfarbe jedes Logos auf!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Lade jedes Logo mit der empfohlenen maximalen Auflösung hoch."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Dies ist kein gültiges Bild, bitte verwende das PNG format!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Dein Service-Logo wurde erfolgreich geändert!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Das Format deines Logos muss PNG sein. Lasse ein Feld aus und das Logo wird nicht geändert."
+
+msgid "Remove this logo"
+msgstr "Entferne dieses Logo."
+
+msgid "View this logo"
+msgstr "Zeige dieses Logo"
+
+msgid "Send a file"
+msgstr "Eine Datei senden"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Wenn hochgeladen, werden deine Freunde dazu aufgefordert, die Datei herunterzuladen."
+
+msgid "Groupchats to join"
+msgstr "Gruppenchats zum Beitreten"
+
+msgid "Purge sent files"
+msgstr "Die gesendeten Dateien leeren"
+
+msgid "would like to send you a file: “%s”."
+msgstr "würde dir gerne eine Datei senden: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "ist damit einverstanden, deine Datei zu empfangen: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "will deine Datei nicht empfangen: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "konnte deine Datei nicht empfangen: “%s”"
+
+msgid "has received a file exchange request: “%s”."
+msgstr "hat eine Anfrage zum Dateiaustausch empfangen: “%s”"
+
+msgid "Available shortcuts:"
+msgstr "Verfügbare Tastenkombinationen:"
+
+msgid "%s removes the chat logs"
+msgstr "%s entfernt die Chat-Protokolle"
+
+msgid "%s joins a groupchat"
+msgstr "%s tritt einem Gruppenchat bei"
+
+msgid "%s closes the chat"
+msgstr "%s schließt den Chat"
+
+msgid "%s shows the user profile"
+msgstr "%s zeigt das Benutzerprofil"
+
+msgid "%s sends a message to the room"
+msgstr "%s sendet eine Nachricht in den Raum"
+
+msgid "%s changes your nickname"
+msgstr "%s ändert deinen Nicknamen"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s sendet eine Nachricht zu jemandem im Raum"
+
+msgid "%s changes the room topic"
+msgstr "%s ändert das Thema des Raumes"
+
+msgid "%s kicks an user of the room"
+msgstr "%s schmeißt jemanden aus dem Raum"
+
+msgid "%s bans an user of the room"
+msgstr "%s bannt jemanden aus dem Raum"
+
+msgid "%s invites someone to join the room"
+msgstr "%s lädt jemanden ein, den Raum beizutreten"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix in eine gemeinnützige soziale Plattform, die du nutzen kannst wo du auch bist, wann immer du willst und egal mit wem du dich unterhalten möchtest."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/en/LC_MESSAGES/main.pot b/jappixmini/jappix/lang/en/LC_MESSAGES/main.pot
new file mode 100644 (file)
index 0000000..42b5b2c
--- /dev/null
@@ -0,0 +1,1856 @@
+# Jappix - An open social platform
+# These are the default english strings of Jappix
+
+# -------------------------------------------------
+
+# License: AGPL
+# Authors: Vanaryon, JanCBorchardt
+# Last revision: 16/01/12
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr ""
+
+msgid "An open social network"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr ""
+
+msgid "The element list on this server could not be obtained!"
+msgstr ""
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr ""
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr ""
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr ""
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr ""
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr ""
+
+msgid "The user that you want to reach is not present in the room."
+msgstr ""
+
+msgid "Please enter the group chat address to join."
+msgstr ""
+
+msgid "Please enter your nickname to join %s."
+msgstr ""
+
+msgid "This room (%s) is protected with a password."
+msgstr ""
+
+msgid "Your browser is out of date!"
+msgstr ""
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Here we go!"
+msgstr ""
+
+msgid "Server"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Remember me"
+msgstr ""
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr ""
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr ""
+
+msgid "Reconnect"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Disconnect"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Add a friend"
+msgstr ""
+
+msgid "Your groupchats"
+msgstr ""
+
+msgid "Manage your favorite groupchats"
+msgstr ""
+
+msgid "More stuff"
+msgstr ""
+
+msgid "Show all friends"
+msgstr ""
+
+msgid "Only show connected friends"
+msgstr ""
+
+msgid "Message archives"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Please select a friend to view the chat history."
+msgstr ""
+
+msgid "Nothing found for: %s"
+msgstr ""
+
+msgid "A short message?"
+msgstr ""
+
+msgid "How are you?"
+msgstr ""
+
+msgid "What are you doing?"
+msgstr ""
+
+msgid "Join a chat"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Talkative"
+msgstr ""
+
+msgid "Away"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Busy"
+msgstr ""
+
+msgid "Mood"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Crazy"
+msgstr ""
+
+msgid "Excited"
+msgstr ""
+
+msgid "Playful"
+msgstr ""
+
+msgid "Happy"
+msgstr ""
+
+msgid "Shocked"
+msgstr ""
+
+msgid "Hot"
+msgstr ""
+
+msgid "Sad"
+msgstr ""
+
+msgid "Amorous"
+msgstr ""
+
+msgid "Confident"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Chores"
+msgstr ""
+
+msgid "Drinking"
+msgstr ""
+
+msgid "Eating"
+msgstr ""
+
+msgid "Exercising"
+msgstr ""
+
+msgid "Grooming"
+msgstr ""
+
+msgid "Appointment"
+msgstr ""
+
+msgid "Inactive"
+msgstr ""
+
+msgid "Relaxing"
+msgstr ""
+
+msgid "Talking"
+msgstr ""
+
+msgid "Traveling"
+msgstr ""
+
+msgid "Working"
+msgstr ""
+
+msgid "View profile"
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Repeat this notice"
+msgstr ""
+
+msgid "Remove this notice"
+msgstr ""
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Identity"
+msgstr ""
+
+msgid "Profile image"
+msgstr ""
+
+msgid "Others"
+msgstr ""
+
+msgid "Personal"
+msgstr ""
+
+msgid "Complete name"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Date of birth"
+msgstr ""
+
+msgid "Contact"
+msgstr ""
+
+msgid "E-mail"
+msgstr ""
+
+msgid "Phone"
+msgstr ""
+
+msgid "Website"
+msgstr ""
+
+msgid "Current"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr ""
+
+msgid "Address"
+msgstr ""
+
+msgid "Street"
+msgstr ""
+
+msgid "City"
+msgstr ""
+
+msgid "Postal code"
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Biography"
+msgstr ""
+
+msgid "Important notice"
+msgstr ""
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr ""
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr ""
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Edit options"
+msgstr ""
+
+msgid "Channel"
+msgstr ""
+
+msgid "Commands"
+msgstr ""
+
+msgid "Sounds"
+msgstr ""
+
+msgid "Inactive"
+msgstr ""
+
+msgid "Privacy"
+msgstr ""
+
+msgid "Message archiving"
+msgstr ""
+
+msgid "Store a history of your chats"
+msgstr ""
+
+msgid "Geolocation"
+msgstr ""
+
+msgid "Empty"
+msgstr ""
+
+msgid "Empty channel"
+msgstr ""
+
+msgid "Persistent"
+msgstr ""
+
+msgid "Maximum notices"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Change password"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Old"
+msgstr ""
+
+msgid "New (2 times)"
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "To"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "unknown"
+msgstr ""
+
+msgid "Unavailable"
+msgstr ""
+
+msgid "is now"
+msgstr ""
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr ""
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr ""
+
+msgid "The image file is not supported or has a bad size."
+msgstr ""
+
+msgid "Reply"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Click here to solve the error"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr ""
+
+msgid "Smiley insertion"
+msgstr ""
+
+msgid "Change style"
+msgstr ""
+
+msgid "Text in bold"
+msgstr ""
+
+msgid "Text in italic"
+msgstr ""
+
+msgid "Underlined text"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Save chat"
+msgstr ""
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr ""
+
+msgid "This chat is empty!"
+msgstr ""
+
+msgid "Generate file!"
+msgstr ""
+
+msgid "Download file!"
+msgstr ""
+
+msgid "Clean current chat"
+msgstr ""
+
+msgid "View chat history"
+msgstr ""
+
+msgid "Show user profile"
+msgstr ""
+
+msgid "Add this contact to your friends"
+msgstr ""
+
+msgid "Add this groupchat to your favorites"
+msgstr ""
+
+msgid "All tabs"
+msgstr ""
+
+msgid "Close this tab"
+msgstr ""
+
+msgid "no subject defined for this room."
+msgstr ""
+
+msgid "Administration panel for this room"
+msgstr ""
+
+msgid "Moderators"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Visitors"
+msgstr ""
+
+msgid "Manage favorite rooms"
+msgstr ""
+
+msgid "Change favorites"
+msgstr ""
+
+msgid "Search a room"
+msgstr ""
+
+msgid "Select a favorite"
+msgstr ""
+
+msgid "Getting the name..."
+msgstr ""
+
+msgid "Gateway"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Room"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Search a room on"
+msgstr ""
+
+msgid "No room found on this server."
+msgstr ""
+
+msgid "Service discovery"
+msgstr ""
+
+msgid "Server to query"
+msgstr ""
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr ""
+
+msgid "Authentications"
+msgstr ""
+
+msgid "Automation"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Collaboration"
+msgstr ""
+
+msgid "Components"
+msgstr ""
+
+msgid "Rooms"
+msgstr ""
+
+msgid "Directories"
+msgstr ""
+
+msgid "Gateways"
+msgstr ""
+
+msgid "News"
+msgstr ""
+
+msgid "Hierarchy"
+msgstr ""
+
+msgid "Proxies"
+msgstr ""
+
+msgid "Publication/Subscription"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Service offline or broken"
+msgstr ""
+
+msgid "Your inbox"
+msgstr ""
+
+msgid "Available actions"
+msgstr ""
+
+msgid "Clean"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "Received"
+msgstr ""
+
+msgid "Subject"
+msgstr ""
+
+msgid "Content"
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Your inbox is empty."
+msgstr ""
+
+msgid "MUC administration"
+msgstr ""
+
+msgid "You administrate this room"
+msgstr ""
+
+msgid "Enter new subject"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Authorizations"
+msgstr ""
+
+msgid "Member list"
+msgstr ""
+
+msgid "Owner list"
+msgstr ""
+
+msgid "Administrator list"
+msgstr ""
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr ""
+
+msgid "Yes, let's do it!"
+msgstr ""
+
+msgid "Your friend is paying attention to the conversation."
+msgstr ""
+
+msgid "Your friend is writing a message..."
+msgstr ""
+
+msgid "Your friend stopped writing a message."
+msgstr ""
+
+msgid "Your friend is doing something else."
+msgstr ""
+
+msgid "Your friend closed the chat."
+msgstr ""
+
+msgid "Requesting this service..."
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "joined the chat room"
+msgstr ""
+
+msgid "left the chat room"
+msgstr ""
+
+msgid "no status"
+msgstr ""
+
+msgid "has been kicked"
+msgstr ""
+
+msgid "has been banned"
+msgstr ""
+
+msgid "no reason"
+msgstr ""
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr ""
+
+msgid "Welcome on %1s, “%2s”."
+msgstr ""
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Resource"
+msgstr ""
+
+msgid "Priority"
+msgstr ""
+
+msgid "Low"
+msgstr ""
+
+msgid "Medium"
+msgstr ""
+
+msgid "High"
+msgstr ""
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr ""
+
+msgid "Share this link with your friends:"
+msgstr ""
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr ""
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr ""
+
+msgid "Manager"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Encrypted"
+msgstr ""
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr ""
+
+msgid "What's up with you?"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "Fetching the social channel..."
+msgstr ""
+
+msgid "You are synchronized with your network."
+msgstr ""
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr ""
+
+msgid "Media viewer"
+msgstr ""
+
+msgid "Browse"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Join"
+msgstr ""
+
+msgid "Automatic"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "No result!"
+msgstr ""
+
+msgid "No notifications."
+msgstr ""
+
+msgid "would like to add you as a friend."
+msgstr ""
+
+msgid "would like you to join this chatroom:"
+msgstr ""
+
+msgid "Do you accept?"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "would like to get authorization."
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Client"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "Local time"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "User profile"
+msgstr ""
+
+msgid "See his/her position on the globe"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "anonymous mode"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Unclassified"
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Ask for authorization"
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Prohibit"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Groupchat"
+msgstr ""
+
+msgid "Jappix Mobile"
+msgstr ""
+
+msgid "Desktop"
+msgstr ""
+
+msgid "Mobile"
+msgstr ""
+
+msgid "Please wait..."
+msgstr ""
+
+msgid "Please enable JavaScript"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Your channel"
+msgstr ""
+
+msgid "Channel of"
+msgstr ""
+
+msgid "More notices..."
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Send"
+msgstr ""
+
+msgid "Unattach the file"
+msgstr ""
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr ""
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr ""
+
+msgid "Internal server error, try later"
+msgstr ""
+
+msgid "Your form has been sent."
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "XMPP links"
+msgstr ""
+
+msgid "Open XMPP links with Jappix"
+msgstr ""
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr ""
+
+msgid "Friends"
+msgstr ""
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr ""
+
+msgid "Don't hide offline friends"
+msgstr ""
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr ""
+
+msgid "Unknown country"
+msgstr ""
+
+msgid "Click to enable"
+msgstr ""
+
+msgid "Click to disable"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Jappix installation"
+msgstr ""
+
+msgid "Welcome to the Jappix installation!"
+msgstr ""
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr ""
+
+msgid "Storage configuration"
+msgstr ""
+
+msgid "Administrator account"
+msgstr ""
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr ""
+
+msgid "Services installation"
+msgstr ""
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr ""
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service name"
+msgstr ""
+
+msgid "Service description"
+msgstr ""
+
+msgid "Connection"
+msgstr ""
+
+msgid "Lock the host"
+msgstr ""
+
+msgid "Anonymous mode"
+msgstr ""
+
+msgid "Registration allowed"
+msgstr ""
+
+msgid "Use a proxy"
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Encryption"
+msgstr ""
+
+msgid "HTTPS storage"
+msgstr ""
+
+msgid "Force HTTPS"
+msgstr ""
+
+msgid "Compression"
+msgstr ""
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr ""
+
+msgid "Groupchat host"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Anonymous host"
+msgstr ""
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Finish"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr ""
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Hosts"
+msgstr ""
+
+msgid "Design"
+msgstr ""
+
+msgid "Repeat"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Horizontal"
+msgstr ""
+
+msgid "Vertical"
+msgstr ""
+
+msgid "Center"
+msgstr ""
+
+msgid "Left"
+msgstr ""
+
+msgid "Right"
+msgstr ""
+
+msgid "Top"
+msgstr ""
+
+msgid "Bottom"
+msgstr ""
+
+msgid "Adapt"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "You have been logged out. Goodbye!"
+msgstr ""
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr ""
+
+msgid "Backgrounds"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr ""
+
+msgid "Notice"
+msgstr ""
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr ""
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr ""
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr ""
+
+msgid "Update in progress"
+msgstr ""
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr ""
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr ""
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr ""
+
+msgid "Daily"
+msgstr ""
+
+msgid "Weekly"
+msgstr ""
+
+msgid "Monthly"
+msgstr ""
+
+msgid "Yearly"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Clean everything"
+msgstr ""
+
+msgid "Purge cache"
+msgstr ""
+
+msgid "Purge logs"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "Purge updates"
+msgstr ""
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Artist"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "The folder is empty."
+msgstr ""
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr ""
+
+msgid "The chosen users have been removed."
+msgstr ""
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "%s days ago"
+msgstr ""
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr ""
+
+msgid "Uncheck all"
+msgstr ""
+
+msgid "Choose"
+msgstr ""
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
\ No newline at end of file
diff --git a/jappixmini/jappix/lang/eo/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/eo/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..3b0d07d
Binary files /dev/null and b/jappixmini/jappix/lang/eo/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/eo/LC_MESSAGES/main.po b/jappixmini/jappix/lang/eo/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..346aa5e
--- /dev/null
@@ -0,0 +1,1870 @@
+# Esperanto translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:45+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Ĝavaskripto mankas en via retumilo, do vi ne povas lanĉi Jappix-on! Bonvolu ripari tion ĉi."
+
+msgid "An open social network"
+msgstr "Malferma socia reto"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix estis interrompita pro reta problemo, cimo aŭ malbona ensaluto (bv. kontroli ke vi tajpis la ĝustan pasvorton). Pardonon por la ĝeno."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "La elementa listo sur ĉi tiu servilo ne povus esti akirita!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Via pasvorto estis ŝanĝita, nun vi povas konekti al via konto kun via nova ensaluta datumo."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Via XMPPa konto estis forigita. Ĝis!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Vi estis adiaŭita de via XMPPa konto. Belan tagon!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "La ĉambro vi aliĝis ŝajnas ke ne ekzistas. Vi devus krei ĝin!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "La retbabilejo estis forigita.Iu alia estos nun kapabla krei ĝi denove."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "La uzanto ke vi deziras atingi ne estas en la ĉambro."
+
+msgid "Please enter the group chat address to join."
+msgstr "Bonvolu tajpi la retbabilejan adreson por aliĝi."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Bonvolu tajpi vian kromnomon por aliĝi %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Ĉi tiu ĉambro (%s) estas protektita kun pasvorto."
+
+msgid "Your browser is out of date!"
+msgstr "Via retumilo tro malnovas!"
+
+msgid "Last %s version is better!"
+msgstr "Lasta %s versio estas pli bona!"
+
+msgid "Login"
+msgstr "Ensaluti"
+
+msgid "Register"
+msgstr "Registri"
+
+msgid "Here we go!"
+msgstr "Ek!"
+
+msgid "Server"
+msgstr "Servilo"
+
+msgid "Password"
+msgstr "Pasvorto"
+
+msgid "Remember me"
+msgstr "Memoru min"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Ĉi tiu ilo estis malaktivigita, vi ne povas uzi ĝin!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Pro reta problemo, vi estis malkonektita. Kio vi deziras fari nun?"
+
+msgid "Reconnect"
+msgstr "Rekonekti"
+
+msgid "Messages"
+msgstr "Mesaĝoj"
+
+msgid "Profile"
+msgstr "Profilo"
+
+msgid "Options"
+msgstr "Opcioj"
+
+msgid "Disconnect"
+msgstr "Elsaluti"
+
+msgid "Filter"
+msgstr "Filtri"
+
+msgid "Add a friend"
+msgstr "Aldoni amikon"
+
+msgid "Your groupchats"
+msgstr "Viaj babilejoj"
+
+msgid "Manage your favorite groupchats"
+msgstr "Administri viajn preferatajn retbabilejojn"
+
+msgid "More stuff"
+msgstr "Pli aĵoj"
+
+msgid "Show all friends"
+msgstr "Montri ĉiojn amikojn"
+
+msgid "Only show connected friends"
+msgstr "Nur montri konektitajn amikojn"
+
+msgid "Message archives"
+msgstr "Mesaĝaj arkivoj"
+
+msgid "Date"
+msgstr "Dato"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Bonvolu elekti amikon por vidi la konversacian historion."
+
+msgid "Nothing found for: %s"
+msgstr "Nenion trovita por: %s"
+
+msgid "A short message?"
+msgstr "Mallonga mesaĝo?"
+
+msgid "How are you?"
+msgstr "Kiel vi fartas?"
+
+msgid "What are you doing?"
+msgstr "Kion vi faras?"
+
+msgid "Join a chat"
+msgstr "Aliĝi babilejo"
+
+msgid "Status"
+msgstr "Stato"
+
+msgid "Available"
+msgstr "Enrete"
+
+msgid "Talkative"
+msgstr "Babilema"
+
+msgid "Away"
+msgstr "Fora"
+
+msgid "Not available"
+msgstr "Nedisponebla"
+
+msgid "Busy"
+msgstr "Okupata"
+
+msgid "Mood"
+msgstr "Humoro"
+
+msgid "None"
+msgstr "Neniu"
+
+msgid "Crazy"
+msgstr "Freneza"
+
+msgid "Excited"
+msgstr "Ekscitema"
+
+msgid "Playful"
+msgstr "Ludema"
+
+msgid "Happy"
+msgstr "Feliĉa"
+
+msgid "Shocked"
+msgstr "Ŝokita"
+
+msgid "Hot"
+msgstr "Varma"
+
+msgid "Sad"
+msgstr "Malfeliĉa"
+
+msgid "Amorous"
+msgstr "Amorema"
+
+msgid "Confident"
+msgstr "Fidema"
+
+msgid "Activity"
+msgstr "Aktiveco"
+
+msgid "Chores"
+msgstr "Taskoj"
+
+msgid "Drinking"
+msgstr "Drinkante"
+
+msgid "Eating"
+msgstr "Manĝante"
+
+msgid "Exercising"
+msgstr "Ekzercante"
+
+msgid "Grooming"
+msgstr "Tualetante"
+
+msgid "Appointment"
+msgstr "Rendevuo"
+
+msgid "Inactive"
+msgstr "Senfara"
+
+msgid "Relaxing"
+msgstr "Ripozante"
+
+msgid "Talking"
+msgstr "Parolante"
+
+msgid "Traveling"
+msgstr "Vojaĝante"
+
+msgid "Working"
+msgstr "Laborante"
+
+msgid "View profile"
+msgstr "Vidi profilon"
+
+msgid "Repeat this notice"
+msgstr "Ripeti tion avizon"
+
+msgid "Remove this notice"
+msgstr "Forigi tion avizon"
+
+msgid "Your profile"
+msgstr "Via profilo"
+
+msgid "Identity"
+msgstr "Identeco"
+
+msgid "Profile image"
+msgstr "Profila bildo"
+
+msgid "Others"
+msgstr "Aliaj"
+
+msgid "Personal"
+msgstr "Persona"
+
+msgid "Complete name"
+msgstr "Tuta nomo"
+
+msgid "Nickname"
+msgstr "Pseŭdonimo"
+
+msgid "First name"
+msgstr "Antaŭa nomo"
+
+msgid "Last name"
+msgstr "Familia nomo"
+
+msgid "Date of birth"
+msgstr "Dato de nasko"
+
+msgid "Contact"
+msgstr "Kontakto"
+
+msgid "E-mail"
+msgstr "Retpoŝto"
+
+msgid "Phone"
+msgstr "Telefono"
+
+msgid "Website"
+msgstr "Retpaĝo"
+
+msgid "Current"
+msgstr "Aktuala"
+
+msgid "Delete"
+msgstr "Forviŝi"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Kio domaĝo! Vi ne havas profilan bildon en via identeca karto!"
+
+msgid "Address"
+msgstr "Adreso"
+
+msgid "Street"
+msgstr "Strato"
+
+msgid "City"
+msgstr "Urbo"
+
+msgid "Postal code"
+msgstr "Poŝtkodo"
+
+msgid "Country"
+msgstr "Lando"
+
+msgid "Biography"
+msgstr "Vivhistorio"
+
+msgid "Important notice"
+msgstr "Grava avizo"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Estu zorgema pri la informojn vi skribas en via profilo, ĉar ĝi povus esti alirita de ĉiuj (eĉ iu kiu vi ne deziras montri)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Ne ĉio estas privata sur XMPP. Via publika profilo (vCard) estas unu el tiuj aferoj."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Alŝuti profila bildo estas forte rekomendita (%s maksimumo), kiel bildo de vi mem, ĉar ĝi faras vin facile rekonebla de viaj amikoj."
+
+msgid "Save"
+msgstr "Akcepti"
+
+msgid "Cancel"
+msgstr "Nuligi"
+
+msgid "Edit options"
+msgstr "Modifi opciojn"
+
+msgid "Channel"
+msgstr "Kanalo"
+
+msgid "Commands"
+msgstr "Komandoj"
+
+msgid "Sounds"
+msgstr "Sonoj"
+
+msgid "Privacy"
+msgstr "Privateco"
+
+msgid "Message archiving"
+msgstr "Mesaĝa enarkivago"
+
+msgid "Store a history of your chats"
+msgstr "Entenas historion de viaj konversacioj"
+
+msgid "Geolocation"
+msgstr "Surtera loko"
+
+msgid "Empty"
+msgstr "Malplena"
+
+msgid "Empty channel"
+msgstr "Malplena kanalo"
+
+msgid "Persistent"
+msgstr "Daŭra"
+
+msgid "Maximum notices"
+msgstr "Maksimumaj avizoj"
+
+msgid "Account"
+msgstr "Konto"
+
+msgid "Change password"
+msgstr "Ŝanĝi pasvorton"
+
+msgid "Delete account"
+msgstr "Forigi konton"
+
+msgid "Old"
+msgstr "Malnova"
+
+msgid "New (2 times)"
+msgstr "Nova (2 fojoj)"
+
+msgid "Continue"
+msgstr "Daŭri"
+
+msgid "To"
+msgstr "Al"
+
+msgid "Close"
+msgstr "Fermi"
+
+msgid "unknown"
+msgstr "nekonata"
+
+msgid "Unavailable"
+msgstr "Nedisponebla"
+
+msgid "is now"
+msgstr "nun estas"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Bonvolu atendi dum via avatar estos alŝutita…"
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Jen! Nova bela profila bildo!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "La bilda dosiero havas nesubtenita tipon aŭ malbonan grandecon."
+
+msgid "Reply"
+msgstr "Respondo"
+
+msgid "Error"
+msgstr "Eraro"
+
+msgid "Click here to solve the error"
+msgstr "Klaku ĉi-tie por solvi la eraron"
+
+msgid "You"
+msgstr "Vi"
+
+msgid "Remove"
+msgstr "Forigi"
+
+msgid "Rename"
+msgstr "Renomi"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Saluton, mi estas %s, mi ŝatus aldoni vin kiel mia amiko."
+
+msgid "Smiley insertion"
+msgstr "Ridetula inserto"
+
+msgid "Change style"
+msgstr "Ŝanĝi stilon"
+
+msgid "Text in bold"
+msgstr "Grasa"
+
+msgid "Text in italic"
+msgstr "Kursiva"
+
+msgid "Underlined text"
+msgstr "Substreka"
+
+msgid "Save chat"
+msgstr "Registrigi babilon"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Klaku sur la sekvanta ligo por akiri la konversacian protokolan dosieron kaj atendu. Tiam klaku denove por akiri la dosieron."
+
+msgid "This chat is empty!"
+msgstr "Tio babilejo estas malplena!"
+
+msgid "Generate file!"
+msgstr "Generi dosieron!"
+
+msgid "Download file!"
+msgstr "Elŝuti dosieron!"
+
+msgid "Clean current chat"
+msgstr "Forviŝi nun babilon"
+
+msgid "View chat history"
+msgstr "Vidi konversacio historio"
+
+msgid "Show user profile"
+msgstr "Montri uzatan profilon"
+
+msgid "Add this contact to your friends"
+msgstr "Aldoni ĉi-tiun kontakton al viaj amikoj"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Aldoni ĉi tiu retbabilejo al via ŝatolisto"
+
+msgid "All tabs"
+msgstr "Tutaj folioj"
+
+msgid "Close this tab"
+msgstr "Fermi tion folion"
+
+msgid "no subject defined for this room."
+msgstr "neniu temo difinita por ĉi tiu ĉambro."
+
+msgid "Administration panel for this room"
+msgstr "Administra panelo por ĉi tiu ĉambro."
+
+msgid "Moderators"
+msgstr "Kontrolantoj"
+
+msgid "Participants"
+msgstr "Partoprenantoj"
+
+msgid "Visitors"
+msgstr "Vizituloj"
+
+msgid "Manage favorite rooms"
+msgstr "Administri preferatajn ĉambrojn"
+
+msgid "Change favorites"
+msgstr "Ŝanĝi ŝatolisto"
+
+msgid "Search a room"
+msgstr "Serĉi babilejon"
+
+msgid "Select a favorite"
+msgstr "Elekti ŝatolistero"
+
+msgid "Getting the name..."
+msgstr "Akirante la nomon…"
+
+msgid "Gateway"
+msgstr "Kluzo"
+
+msgid "Name"
+msgstr "Nomo"
+
+msgid "Room"
+msgstr "Babilejo"
+
+msgid "Add"
+msgstr "Aldoni"
+
+msgid "Edit"
+msgstr "Modifi"
+
+msgid "Search a room on"
+msgstr "Serĉi babilejon sur"
+
+msgid "No room found on this server."
+msgstr "Neniu ĉambro trovita sur ĉi tiu servilo."
+
+msgid "Service discovery"
+msgstr "Serva eltrovo"
+
+msgid "Server to query"
+msgstr "Servilo por pridemandi"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Pardonu, sed la ento ne revenis ajnan rezulton!"
+
+msgid "Accounts"
+msgstr "Kontoj"
+
+msgid "Authentications"
+msgstr "Aŭtentokontroloj"
+
+msgid "Automation"
+msgstr "Aŭtomatigo"
+
+msgid "Clients"
+msgstr "Klientoj"
+
+msgid "Collaboration"
+msgstr "Kunlaborado"
+
+msgid "Components"
+msgstr "Komponento"
+
+msgid "Rooms"
+msgstr "Babilejoj"
+
+msgid "Directories"
+msgstr "Dosierujoj"
+
+msgid "Gateways"
+msgstr "Kluzoj"
+
+msgid "News"
+msgstr "Novaĵoj"
+
+msgid "Hierarchy"
+msgstr "Hierarkio"
+
+msgid "Proxies"
+msgstr "Prokuraj serviloj"
+
+msgid "Publication/Subscription"
+msgstr "Eldona/Abono"
+
+msgid "Storage"
+msgstr "Konservado"
+
+msgid "Service offline or broken"
+msgstr "Servo elretan aŭ rompita"
+
+msgid "Your inbox"
+msgstr "Via enirkesto"
+
+msgid "Available actions"
+msgstr "Haveblaj agoj"
+
+msgid "Clean"
+msgstr "Purigi"
+
+msgid "New"
+msgstr "Nova"
+
+msgid "Received"
+msgstr "Ricevitaj"
+
+msgid "Subject"
+msgstr "Temo"
+
+msgid "Content"
+msgstr "Enhavo"
+
+msgid "Send message"
+msgstr "Sendi mesaĝon"
+
+msgid "Your inbox is empty."
+msgstr "Via enirkesto estas malplene."
+
+msgid "MUC administration"
+msgstr "Retbabileja administrado."
+
+msgid "You administrate this room"
+msgstr "Vi administras ĉi-tiun ĉambron"
+
+msgid "Enter new subject"
+msgstr "Tajpu novan subjekton"
+
+msgid "Configuration"
+msgstr "Agordoj"
+
+msgid "Authorizations"
+msgstr "Aŭtentigoj"
+
+msgid "Member list"
+msgstr "Membra listo"
+
+msgid "Owner list"
+msgstr "Posedanta listo"
+
+msgid "Administrator list"
+msgstr "Administranta listo"
+
+msgid "Outcast list"
+msgstr "Forĵetuloj listo"
+
+msgid "Add an input"
+msgstr "Aldonas enigon"
+
+msgid "Destroy this MUC"
+msgstr "Detrui la retbabilejon"
+
+msgid "Yes, let's do it!"
+msgstr "Jes, faru ni!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Via amiko estas atentita al la konversacio."
+
+msgid "Your friend is writing a message..."
+msgstr "Via amiko estas skribanti mesaĝon... "
+
+msgid "Your friend stopped writing a message."
+msgstr "Via amiko haltis skribi mesaĝon."
+
+msgid "Your friend is doing something else."
+msgstr "Via amiko estas farante ion alia."
+
+msgid "Your friend closed the chat."
+msgstr "Via amiko fermis la konversacion."
+
+msgid "Requesting this service..."
+msgstr "Petanta ĉi-tiun servon…"
+
+msgid "Loading"
+msgstr "Ŝargi"
+
+msgid "joined the chat room"
+msgstr "aliĝis al la babilejo"
+
+msgid "left the chat room"
+msgstr "foriris la babilejo"
+
+msgid "no status"
+msgstr "neniu stato"
+
+msgid "has been kicked"
+msgstr "estas elpelita"
+
+msgid "has been banned"
+msgstr "estis ekskludita"
+
+msgid "no reason"
+msgstr "neniu motivo"
+
+msgid "Communicate with the entire world!"
+msgstr "Komuniku kun la tuta mondo!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Kontaktu la milionojn de uzantoj kiu nuntempe uzas la XMPPan reton, kiel vi faras uzante Jappix-on. Aliĝu la komunumon kaj restu libere!"
+
+msgid "Hi there!"
+msgstr "Saluton!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Bonvenon en %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Ensalutu al via ekzistanta XMPP konto, aŭ krei novan senkoste!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix estas malferma-fonta projekto de PostPro, neprofita organizo kiu grande helpas nin."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Ensalutu kun via ekzistanta XMPP-a konto. Vi ankaŭ povas uzi la %s por aliĝi retbabilejon."
+
+msgid "Previous"
+msgstr "Antaŭa"
+
+msgid "General"
+msgstr "Ĝenerala"
+
+msgid "Advanced"
+msgstr "Krome"
+
+msgid "Resource"
+msgstr "Risurco"
+
+msgid "Priority"
+msgstr "Prioritato"
+
+msgid "Low"
+msgstr "Malgrava"
+
+msgid "Medium"
+msgstr "Norma"
+
+msgid "High"
+msgstr "Grava"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Eniru la retbablejon vi deziras aliĝi, kaj la kromnomon kiu vi deziras. Vi ankaŭ povas reveni al la %s."
+
+msgid "login page"
+msgstr "ensaluta paĝo"
+
+msgid "Share this link with your friends:"
+msgstr "Kundividu ĉi-tiun ligon kun viaj amikoj:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Registru novan XMPPan konton por aligi viajn amikojn sur via propra socia nubo. Tio estas simpla!"
+
+msgid "Required"
+msgstr "Postulita"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Vi estis registrita, jen via XMPPa adreso:"
+
+msgid "Manager"
+msgstr "Administrilo"
+
+msgid "Project"
+msgstr "Projekto"
+
+msgid "Encrypted"
+msgstr "Ĉifrita"
+
+msgid "Unencrypted"
+msgstr "Neĉifrita"
+
+msgid "Where are you?"
+msgstr "Kie vi estas?"
+
+msgid "What's up with you?"
+msgstr "Kio nova?"
+
+msgid "Fetching the social channel..."
+msgstr "Akirante la socian kanalon..."
+
+msgid "You are synchronized with your network."
+msgstr "Vi estas samtempigita kun via reto."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Ne povas sendi ion-ajn: vi nur povas ricevi avizojn!"
+
+msgid "Media viewer"
+msgstr "Aŭdvidaĵa legilo"
+
+msgid "Browse"
+msgstr "Foliumi"
+
+msgid "Command"
+msgstr "Komando"
+
+msgid "Subscribe"
+msgstr "Aboni"
+
+msgid "Join"
+msgstr "Aliĝi"
+
+msgid "Automatic"
+msgstr "Aŭtomata"
+
+msgid "Search"
+msgstr "Serĉi"
+
+msgid "No result!"
+msgstr "Neniu trafo!"
+
+msgid "No notifications."
+msgstr "Neniuj sciigoj."
+
+msgid "would like to add you as a friend."
+msgstr "ŝatus aldoni vin kiel amiko."
+
+msgid "would like you to join this chatroom:"
+msgstr "ŝatus vin aliĝi ĉi tiun babilejon:"
+
+msgid "Do you accept?"
+msgstr "Ĉu vi akceptas?"
+
+msgid "Yes"
+msgstr "Jes"
+
+msgid "No"
+msgstr "Ne"
+
+msgid "would like to get authorization."
+msgstr "ŝatus akiri rajtigon."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Ĉu vi deziras vidi la amikojn %s sugestas vin?"
+
+msgid "Submit"
+msgstr "Sendi"
+
+msgid "Client"
+msgstr "Kliento"
+
+msgid "System"
+msgstr "Sistemo"
+
+msgid "Local time"
+msgstr "Loka tempo"
+
+msgid "Comments"
+msgstr "Komentoj"
+
+msgid "User profile"
+msgstr "Uzanta profilo"
+
+msgid "See his/her position on the globe"
+msgstr "Vidi lia/ŝia pozicio sur Tero"
+
+msgid "Confirm"
+msgstr "Konfirmi"
+
+msgid "anonymous mode"
+msgstr "anonima modo"
+
+msgid "Groups"
+msgstr "Grupoj"
+
+msgid "Unclassified"
+msgstr "Neklasigita"
+
+msgid "Authorize"
+msgstr "Rajtigi"
+
+msgid "Ask for authorization"
+msgstr "Peto por rajtigo"
+
+msgid "Unblock"
+msgstr "Malbloki"
+
+msgid "Prohibit"
+msgstr "Malpermesi"
+
+msgid "Block"
+msgstr "Bloki"
+
+msgid "Chat"
+msgstr "Babilado"
+
+msgid "Groupchat"
+msgstr "Retbabilejo"
+
+msgid "Jappix Mobile"
+msgstr "Poŝtelefona Jappix"
+
+msgid "Desktop"
+msgstr "Surtabla versio"
+
+msgid "Mobile"
+msgstr "Poŝtelefona versio"
+
+msgid "Please wait..."
+msgstr "Momenton…"
+
+msgid "Please enable JavaScript"
+msgstr "Bonvolu enŝalti Ĝavoskripton"
+
+msgid "Your channel"
+msgstr "Via kanalo"
+
+msgid "Channel of"
+msgstr "Kanalo da"
+
+msgid "More notices..."
+msgstr "Pli da avizoj…"
+
+msgid "Attach a file"
+msgstr "Alligas dosieron "
+
+msgid "Send"
+msgstr "Sendi"
+
+msgid "Unattach the file"
+msgstr "Malalligas dosieron "
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Eraro okazis dum via dosiero elŝutado: eble ĝi estas tro granda (%s maksimuma) aŭ malpermesita!"
+
+msgid "Authorization failed"
+msgstr "Rajtigo malsuksesis"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrigo malsuksesis. Bonvolu elekti alian salutnomon."
+
+msgid "Service unavailable"
+msgstr "Maldisponebla servo"
+
+msgid "Internal server error, try later"
+msgstr "Interna servila eraro, provas poste"
+
+msgid "Your form has been sent."
+msgstr "Via formo estis sendita."
+
+msgid "Application"
+msgstr "Aplikaĵo"
+
+msgid "XMPP links"
+msgstr "XMPPa ligoj"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Malfermi XMPPan ligojn kun Jappix"
+
+msgid "changed the subject to:"
+msgstr "ŝanĝis la temon al:"
+
+msgid "Welcome!"
+msgstr "Bonvenon!"
+
+msgid "Friends"
+msgstr "Amikoj"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Bonvenon ĉe Jappix, via propra socia nubo!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Antaŭ ol vi komencas uzi ĝin, vi devos ŝanĝi kelkajn agordojn, serĉi amikojn kaj kompletigi vian profilon."
+
+msgid "Enable notification sounds"
+msgstr "Enŝalti sciigajn sonojn"
+
+msgid "Share your position on the globe"
+msgstr "Komuniku vian lokon sur Tero"
+
+msgid "Offline friends"
+msgstr "Eksterretaj amikoj"
+
+msgid "Don't hide offline friends"
+msgstr "Ne kaŝi eksterretajn amikojn"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Uzi ĉi tiun ilon por trovi viajn amikojn sur la servilo kiu vi ĝus uzas nun, aŭ aldoni ilin poste."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Bonege! Nun, vi povas kunuzi Jappix kun viaj amikoj!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Kiam vi premos la “savi” butonon, la profila redaktorilo estos malfermita. Feliĉan societumon!"
+
+msgid "Share Jappix on %s"
+msgstr "Kunuzigi Jappix-on ĉe %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Uzante Jappix-on, malferma socia platformo. Mi estas %s!"
+
+msgid "Unknown name"
+msgstr "Nekonata nomo"
+
+msgid "Unknown country"
+msgstr "Nekonata lando"
+
+msgid "Click to enable"
+msgstr "Premi por enŝalti"
+
+msgid "Click to disable"
+msgstr "Premi por elŝalti"
+
+msgid "Installation"
+msgstr "Instalado"
+
+msgid "Jappix installation"
+msgstr "Jappix-a instalado"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Bonvenon en la instalado de Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Ĉi tiu ilo helpos vin instali Jappix-on rapide, la unua  XMPP-bazita socian platformon, sur via servilo. Vi ne eĉ devas ajnan teknikan scion."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Jen la instaladaj paŝoj:"
+
+msgid "Welcome"
+msgstr "Bonvenon"
+
+msgid "Storage configuration"
+msgstr "Konservada agordo"
+
+msgid "Administrator account"
+msgstr "Administranta konto"
+
+msgid "Main configuration"
+msgstr "Ĉefa agordo"
+
+msgid "Hosts configuration"
+msgstr "Agordo de gastigoj"
+
+msgid "Services installation"
+msgstr "Instalado de servoj"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Se la nuna lingvo ne kongruas la vian (%1s), vi povas paroligi Jappix %2s ĝi estos savita."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Se vi deziras akiri helpon pri la Jappix-a instalaĵo kaj agordaĵo, vi povas uzi nian tutan dokumentaron, havebla ĉe:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Estas tempo por konstrui vian propran socian nubon: nur iru al la sekvanta paŝo!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix entenas persistan datumon (kiel komunaj dosieroj, konversaciaj ŝtipoj, via propra muziko kaj ĝia konfiguracio) en ununura gardata konservada dosierujo."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix devas esti kapabla skribi en ĉi tiu teko krei ĝia sub-adresaroj. Se ne, vi devas fiksi la rajtojn al %1s aŭ ŝanĝi la tekan posedanton al %2s (dependanta de via konfiguracio)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "La dosierujo estas skribebla, vi povas daŭri!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix ebligas vin administri vian konfiguron, instali novajn kromaĵojn aŭ serĉi ĝisdatigojn. Tio estas kial vi devas krei administrantan konton por aliri la manaĝeron."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Kiam Jappix estos instalita, ĵus klaku sur la manaĝera ligo ĉe la hejmpaĝo por aliri ĝin."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Ohoh, vi perdiĝis ion aŭ la du pasvortoj ne kongruas!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix necesas ke vi specifu kelkajn valorojn por funkcii. Bonvolu ĝustigi la sekvantajn enigojn (aŭ teni la apriorajn valorojn, kiu estas sufiĉa por plejpartoj de homoj)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Notu ke se vi ne specifas valoron kiu estas deviga, ĝi estos aŭtomate kompletigita kun la apriora unu."
+
+msgid "User"
+msgstr "Uzanto"
+
+msgid "Service"
+msgstr "Servo"
+
+msgid "Service name"
+msgstr "Serva nomo"
+
+msgid "Service description"
+msgstr "Serva priskribo"
+
+msgid "Connection"
+msgstr "Konekto"
+
+msgid "Lock the host"
+msgstr "Ŝlozi la gastigon"
+
+msgid "Anonymous mode"
+msgstr "Sennoma modo"
+
+msgid "Registration allowed"
+msgstr "Registriĝo permesita"
+
+msgid "Use a proxy"
+msgstr "Uzi prokurilon"
+
+msgid "Encryption"
+msgstr "Ĉifrado"
+
+msgid "HTTPS storage"
+msgstr "HTTPS-a konservado"
+
+msgid "Force HTTPS"
+msgstr "Perforti HTTPS-n"
+
+msgid "Compression"
+msgstr "Densigo"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Ĉi-tiu paĝo helpas vin por specifi la apriorajn gastigojn kiu konektos al Jappix. Vi povas lasi ĝin kiel ĝi estas, kaj daŭri se vi deziras uzi la oficialajn servajn gastigojn."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Eble vi ne scias kiu BOSH-a servilo estas? Fakte, tio ĉi estas transsendado inter Jappix kliento kaj XMPP-a servilo, kiu estas necesa pro teknikaj limoj."
+
+msgid "Main host"
+msgstr "Ĉefa gastigo"
+
+msgid "Groupchat host"
+msgstr "Retbabileja gastigo"
+
+msgid "Anonymous host"
+msgstr "Sennoma gastigo"
+
+msgid "Directory host"
+msgstr "Dosieruja gastigo"
+
+msgid "BOSH host"
+msgstr "BOSH-a gastigo"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Vi povas instali kelkajn kromaĵojn sur via servilo, etendi vian Jappix-an funkciojn. Kelkaj aliaj povus esti modifita, pro sekurecaj restriktoj kiuj estas fiksita apriore."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Por fari tion-ĉi, vi devas esti kapabla aliri la via servila ŝelo, kaj esti ensalutita kiel administranto. Memori ĉi-tion ne estas deviga, Jappix laboros sen ĉi-tiuj kapsuloj, sed kelkaj el funkcioj estos malhaveblaj."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Kiam tiam vi finigis la agordon, Jappix produktos la kaŝdosierojn. Povus esti malrapida, bv. atendi ĝis la aplikaĵo estos montrita kaj ne premu iu-ajnan butonon."
+
+msgid "Thanks for using Jappix!"
+msgstr "Dankon por uzi Jappix-n!"
+
+msgid "Next"
+msgstr "Laŭ"
+
+msgid "Finish"
+msgstr "Fini"
+
+msgid "Check again"
+msgstr "Denove kontroli"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "La dosierujo ne estas skribebla. Bonvolu agordi la ĝustajn permesojn al la %s dosierujon."
+
+msgid "%s is installed on your system."
+msgstr "%s estas instalita sur via sistemo."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s ne estas instalita sur via sistemo. Vi devus instali %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP maksimuma alŝuta grando estas sufiĉa (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP maksimuma alŝuta grando ne estas sufiĉa (%1s). Vi devus defini ĝin inter %2s kaj %3s."
+
+msgid "Jappix manager"
+msgstr "Jappix-a administrilo"
+
+msgid "Manager access"
+msgstr "Administrila aliro"
+
+msgid "Statistics"
+msgstr "Statistiko"
+
+msgid "Hosts"
+msgstr "Gastigoj"
+
+msgid "Design"
+msgstr "Fasonado"
+
+msgid "Repeat"
+msgstr "Ripeti"
+
+msgid "All"
+msgstr "Ĉio"
+
+msgid "Horizontal"
+msgstr "Horizontala"
+
+msgid "Vertical"
+msgstr "Vertikala"
+
+msgid "Center"
+msgstr "Centre"
+
+msgid "Left"
+msgstr "Maldekstre"
+
+msgid "Right"
+msgstr "Dekstre"
+
+msgid "Top"
+msgstr "Supre"
+
+msgid "Bottom"
+msgstr "Fundo"
+
+msgid "Adapt"
+msgstr "Adapti"
+
+msgid "Color"
+msgstr "koloro"
+
+msgid "Users"
+msgstr "Uzantoj"
+
+msgid "Updates"
+msgstr "Ĝisdatigoj"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Tio ĉi estas restriktita zonon: nur la rajtigitaj uzantoj povus administri ĉi-tiun Jappix-an nodon."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Bonvolu uzi la suban formularon por ensaluti en la administrita panelo."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Por plibonigi sekurecon, sesioj estas limigitaj per tempo kaj kiam via retumilo estos fermita, vi estos adiaŭita."
+
+msgid "Credentials"
+msgstr "Legitimaĵo"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Vi estis elsalutita. Ĝis!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Hoho, vi ne povus esti rekonita kiel valida administranto. Bonvolu kontroli vian leĝitimaĵon!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Bazan statistikon estas faritaj per Jappix pri kelkaj gravaj aferoj. Vi povas trovi ilin malsupre."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Ŝanĝu vian Jappix-an nodna konfiguracion kun ĉi-tiu ilo."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Ŝanĝu la XMPP-an gastigojn ke ĉi-tiu Jappix-a nodo povas servi kun ĉi-tiu ilo."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Ĉiuj Jappix-a noda konservitaj dosierojn povas esti administrita kun ĉi tiu ilo: bonvolu elekti subdosierujon kaj komenci redakti ĝian enhavon!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix estas tute tajlorebla: vi povas ŝanĝi ĝian fasonadon ĉi-tie."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Tio-ĉi ne estas valida bildo. Bonvolu uzi PNG, GIF aŭ JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "La bildo ne povus esti ricevita. Bonvolu provi denove."
+
+msgid "Your image was added to the list!"
+msgstr "Vian bildon estas aldonita al la listo!"
+
+msgid "Changes saved!"
+msgstr "Ŝanĝoj konservitaj"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Vi povas difini pli ol unu administranto por ĉi-tiu Jappix nodo. Vi ankaŭ povas ŝanĝi pasvorton kun ĉi tiu ilo."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Ĝisdatigu vian Jappix-an nodon kun ĉi-tiu ilo, aŭ kontroli se nova estas havebla. Informoj pri la plej lasta versio estas ankaŭ montritaj (en la angla)."
+
+msgid "Access statistics"
+msgstr "Iri al statistiko"
+
+msgid "Share statistics"
+msgstr "Disvastigi statistikon"
+
+msgid "Other statistics"
+msgstr "Alia statistiko"
+
+msgid "January"
+msgstr "Januaro"
+
+msgid "February"
+msgstr "Februaro"
+
+msgid "March"
+msgstr "Marto"
+
+msgid "April"
+msgstr "Aprilo"
+
+msgid "May"
+msgstr "Majo"
+
+msgid "June"
+msgstr "Junio"
+
+msgid "July"
+msgstr "Julio"
+
+msgid "August"
+msgstr "Aŭgusto"
+
+msgid "September"
+msgstr "Septembro"
+
+msgid "October"
+msgstr "Oktobro"
+
+msgid "November"
+msgstr "Novembro"
+
+msgid "December"
+msgstr "Decembro"
+
+msgid "Monday"
+msgstr "lundo"
+
+msgid "Tuesday"
+msgstr "mardo"
+
+msgid "Wednesday"
+msgstr "merkredo"
+
+msgid "Thursday"
+msgstr "jaŭdo"
+
+msgid "Friday"
+msgstr "vendredo"
+
+msgid "Saturday"
+msgstr "sabato"
+
+msgid "Sunday"
+msgstr "dimanĉo"
+
+msgid "Total"
+msgstr "Totala"
+
+msgid "Cache"
+msgstr "Kaŝmemoro"
+
+msgid "Logs"
+msgstr "Protokoloj"
+
+msgid "Music"
+msgstr "Muziko"
+
+msgid "Backgrounds"
+msgstr "Fonoj"
+
+msgid "Share"
+msgstr "Disvastigi"
+
+msgid "Background"
+msgstr "Fono"
+
+msgid "Notice"
+msgstr "Avizo"
+
+msgid "Your design preferences have been saved!"
+msgstr "Viaj fasonaj preferoj estis savita!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Bonvolu kontroli viajn enigojn: io mankas!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Ŝanĝu vian Jappix-an nodan fonon kun ĉi tiu ilo. Vi povas agordi propran koloron aŭ alŝutitan bildon. Lasu vian kreecon flui!"
+
+msgid "Use default background"
+msgstr "Uzi aprioran fonon"
+
+msgid "Use your own image"
+msgstr "Uzi vian propran bildon"
+
+msgid "Select a background to use and change the display options."
+msgstr "Elektu fonon por uzi kaj ŝanĝi la vidigajn elektojn."
+
+msgid "Use your own color"
+msgstr "Uzi vian propran koloron"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Tajpu la deksesuman koloran valoron kiun vi deziras uzi kiel fono."
+
+msgid "Manage backgrounds"
+msgstr "Administri fonojn"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Vi povas aldoni novan fonon al la listo kun ĉi-tiu ilo. Bonvolu sendi validan bildon."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Se vi deziras forigi kelkajn fonojn, uzu la suban retumilon."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Difinu ĉefpaĝan avizon por ĉiuj viaj uzantoj, ekzemple averto, grava mesaĝo aŭ reklamo kun ĉi-tiu ilo."
+
+msgid "Simple notice"
+msgstr "Simple avizo"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Ĉi-tiu avizo nur bezonas simplan tekston por esti montrita, sed kodo ne estas permesita!"
+
+msgid "Advanced notice"
+msgstr "Kroma avizo"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Vi povas agordi vian avizon kun enigita HTML, CSS kaj Ĝavoskripto, sed vi bezonas kodi la stilon."
+
+msgid "Available updates"
+msgstr "Haveblaj ĝisdatigoj"
+
+msgid "What's new?"
+msgstr "Kio nova?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Viaj konservaj dosierujon ne estas skribeblaj. Bonvolu apliki la ĝustajn rajtojn!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s povas kaŭzi problemojn al la prokurilo. Bonvolu pliigi %2s valoro ĝis %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Vi estas uzanta konstruatan version de Jappix. Ĝisdatigu ĝin tra nia deponejo plenumigante: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Nova versio de Jappix estas havebla! Kontrolu kion estas nova kaj lanĉu la ĝisdatigon!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Via versio ne estas ĝisdatiga. Bonvolu nun ĝisdatigi al %s, klakante ĉi-tie!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Via versio ŝajnas esti ĝisdatiga, sed vi povas kontroli ĝisdatigojn mane, klakante ĉi-tie."
+
+msgid "Check for updates"
+msgstr "Kontroli ĝisdatigoj"
+
+msgid "Update in progress"
+msgstr "Ĝisdatigante…"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix estis ĝisdatigita: vi nun uzas la plej lastan version. Amuziĝu!"
+
+msgid "The update has failed! Please try again later."
+msgstr "La ĝisdatigo fiaskis! Bonvolu provi denove poste."
+
+msgid "Downloading package..."
+msgstr "Elŝutante pakaĵon…"
+
+msgid "Removing current Jappix system files..."
+msgstr "Forigas nunajn Jappix-an sistemajn dosierojn…"
+
+msgid "Extracting package..."
+msgstr "Eltirante pakaĵon…"
+
+msgid "Regenerating storage folder tree..."
+msgstr "Regenerante konservadan dosierujan arbon..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix estas nun ĝisdatigita!"
+
+msgid "Aborted: socket error!"
+msgstr "Ĉesita: inga eraro!"
+
+msgid "Aborted: buffer error!"
+msgstr "Ĉesita: bufra eraro!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Ĉesita: ĉio ne skribeblas!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Ĉesita: ne povas eltiri la pakaĵon!"
+
+msgid "Visits"
+msgstr "Vizitoj"
+
+msgid "Daily"
+msgstr "Ĉiutaga"
+
+msgid "Weekly"
+msgstr "Ĉiusemajna"
+
+msgid "Monthly"
+msgstr "Ĉiumonata"
+
+msgid "Yearly"
+msgstr "Ĉiujara"
+
+msgid "Size"
+msgstr "Grando"
+
+msgid "Clean everything"
+msgstr "Viŝi ĉion"
+
+msgid "Purge cache"
+msgstr "Viŝi kaŝmemoron"
+
+msgid "Purge logs"
+msgstr "Viŝi protokolojn"
+
+msgid "Purge updates"
+msgstr "Viŝi ĝisdatigojn"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "La konservada dosiero tiun, kiun vi volus viŝi estas nun malplena!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Tenu vian Jappix-an nodon freŝe kaj rapide, viŝu la konservadan dosieron regule!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Alŝutu vian muzikon (Ogg Vorbis, Mp3 aŭ WAV) por esti kapabla aŭskulti ĝin ĉe Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "La dosiero vi deziras alŝuti devus esti malpli grande ol %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Estu vigla pri kion viaj uzantoj konservas en via servilo, kaj forigu nedezireman enhavon kun ĉi tiu ilo."
+
+msgid "Title"
+msgstr "Titolo"
+
+msgid "Artist"
+msgstr "Artisto"
+
+msgid "Album"
+msgstr "Albumo"
+
+msgid "File"
+msgstr "Dosiero"
+
+msgid "Upload"
+msgstr "Alŝuti"
+
+msgid "The folder is empty."
+msgstr "La dosieraro estas malplena."
+
+msgid "The music could not be received, please retry!"
+msgstr "La muziko ne povus esti ricevita, bonvolu provi denove!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Tio ĉi ne estas valida muzika dosiero. Bonvolu kodigi en Ogg Vorbis, Mp3 aŭ WAV."
+
+msgid "Your music has been added!"
+msgstr "Via muziko ĵus estas aldonita!"
+
+msgid "The selected elements have been removed."
+msgstr "La elektitajn elementojn estas forigita."
+
+msgid "You must select elements to remove!"
+msgstr "Vin devas elekti forigendajn elementojn!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Aldonu novan uzanton kun ĉi-tiu ilo, aŭ ŝanĝu pasvorton (tajpu ekzistantan salutnomon). Bonvolu sendi fortan pasvorton!"
+
+msgid "Manage"
+msgstr "Administri"
+
+msgid "List"
+msgstr "Listo"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Forigu uzantojn kun ĉi-tiu ilo. Notu ke vi ne povas forigi uzanton se li estas la ununura restante."
+
+msgid "The user has been added!"
+msgstr "La uzanto estis aldonita!"
+
+msgid "The chosen users have been removed."
+msgstr "La elektitaj uzantoj estis forigita."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Vi devas elekti unu aŭ pli da uzantoj por esti forigi!"
+
+msgid "Yesterday"
+msgstr "Hieraŭ"
+
+msgid "%s days ago"
+msgstr "%s tagoj antaŭe"
+
+msgid "User currently active"
+msgstr "Uzanto nune aktiva"
+
+msgid "Last seen: %s"
+msgstr "Laste vidita: %s"
+
+msgid "Inactive since: %s"
+msgstr "Malaktiva ekde: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Via amiko ŝajnas ke li ne ricevas viajn mesaĝojn! "
+
+msgid "Static content server"
+msgstr "Senmova enhava servilo"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Tiu estas la senmova enhava servilo por %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Proponi amikojn"
+
+msgid "Check all"
+msgstr "Enŝalti ĉion"
+
+msgid "Uncheck all"
+msgstr "Elŝalti ĉion"
+
+msgid "Choose"
+msgstr "Elekti"
+
+msgid "List name"
+msgstr "Lista nomo"
+
+msgid "Allow"
+msgstr "Permesi"
+
+msgid "Deny"
+msgstr "Malpermesi"
+
+msgid "Group"
+msgstr "Groupo"
+
+msgid "Subscription"
+msgstr "Abono"
+
+msgid "Both"
+msgstr "Ambaŭ"
+
+msgid "From"
+msgstr "De"
+
+msgid "Everybody"
+msgstr "Ĉiuj"
+
+msgid "Send messages"
+msgstr "Sendi mesaĝojn"
+
+msgid "Send queries"
+msgstr "Sendi petojn"
+
+msgid "See my status"
+msgstr "Vidi mia stato"
+
+msgid "Send his/her status"
+msgstr "Sendi lia/ŝia staton"
+
+msgid "Everything"
+msgstr "Ĉio"
+
+msgid "Item"
+msgstr "Elemento"
+
+msgid "Order"
+msgstr "Ordo"
+
+msgid "Active for this session"
+msgstr "Aktiva por tiu seanco"
+
+msgid "Always active"
+msgstr "Ĉiam aktiva"
+
+msgid "User directory"
+msgstr "Jarlibro de uzantoj"
+
+msgid "Search a friend"
+msgstr "Serĉi amikon"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "La petita funkcio ne estas efektivigita de la ricevinto aŭ servilo kaj sekve ne povas esti pretigita."
+
+msgid "This is a repeat from %s"
+msgstr "Tio estas ripeto de %s"
+
+msgid "Loading comments..."
+msgstr "Ĉarĝante komentojn…"
+
+msgid "Type your comment here..."
+msgstr "Tajpu vian komenton ĉi-tie…"
+
+msgid "Could not get the comments!"
+msgstr "Ne povis akiri komentojn!"
+
+msgid "Show comments"
+msgstr "Montri komentojn"
+
+msgid "Send him/her a message"
+msgstr "Sendi mesaĝon al li/ŝi"
+
+msgid "Start a chat with him/her"
+msgstr "Komenci babilon kun li/ŝi"
+
+msgid "Media integration"
+msgstr "Aŭdvidaĵo integrado"
+
+msgid "Comments locked!"
+msgstr "Komentoj ŝlositaj!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Tajpu ion vi deziras disvastigi al viaj amikoj..."
+
+msgid "changed his/her nickname to %s"
+msgstr "ŝanĝis lia/ŝia kromnomo al %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "komentis elementon kiun vi sekvas: “%s”."
+
+msgid "Hide"
+msgstr "Kaŝi"
+
+msgid "liked your post: “%s”."
+msgstr "ŝatas vian afiĝon: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "citigis vin ie: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "publikigis sur via muro: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "markis vin sur bildon (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "markis vin sur videon (%s)."
+
+msgid "Show"
+msgstr "Montri"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Bezoni helpon? Vi povus legi nian dokumentaran paĝon pri kiel plenigi ĉi-tiun formularon!"
+
+msgid "Pubsub host"
+msgstr "Pubsub-a gastigo"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix estas genia socia platformo, kiu vi povas aliri ie-ajn vi estas, iam-ajn vi deziras kaj komuniki kun kiu-ajn vi deziras."
+
+msgid "Manager link"
+msgstr "Administra ligilo"
+
+msgid "User uploads server"
+msgstr "Uzanta alŝutitaj servilo"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Ĉi-tio estas la uzanta alŝutaj servilo por %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Emblemo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Vi povas agordi vian propran servan emblemon por anstataŭigi la aprioran unun. Zorgu la grandon kaj la ĉefan koloron de ĉiu emblemo!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Alŝutu ĉiun emblemon kun la rekomenda maksimuma bildera grandeco."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Ne estas valida bildo. Bonvolu uzi la formato PNG."
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Via serva emblemo estas sukcese ŝanĝita!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Via emblema formato devus esti PNG. La emblemon ne estos ŝanĝita se vi lasu malplenan kampon."
+
+msgid "Remove this logo"
+msgstr "Forviŝi ĉi-tiun emblemon"
+
+msgid "View this logo"
+msgstr "Vidi ĉi-tiun emblemon"
+
+msgid "Send a file"
+msgstr "Sendi dosieron"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Kiam alŝutita, via amiko estos invitata por elŝuti la senditan dosieron."
+
+msgid "Groupchats to join"
+msgstr "Alireblaj retbabilejoj"
+
+msgid "Purge sent files"
+msgstr "Viŝi senditajn dosierojn"
+
+msgid "would like to send you a file: “%s”."
+msgstr "deziras sendi al vi dosieron: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "akceptis ricevi vian dosieron:“%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "malakceptis ricevi vian dosieron:“%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "ne povas ricevi vian dosieron: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "ricevis dosieran interŝanĝan peton:“%s”."
+
+msgid "Available shortcuts:"
+msgstr "Haveblaj fulmoklavoj:"
+
+msgid "%s removes the chat logs"
+msgstr "%s forigas la babilemajn protokoldosierojn"
+
+msgid "%s joins a groupchat"
+msgstr "%s aliris retbabilejon"
+
+msgid "%s closes the chat"
+msgstr "%s fermas la babilejon"
+
+msgid "%s shows the user profile"
+msgstr "%s montras la uzantan profilon"
+
+msgid "%s sends a message to the room"
+msgstr "%s sendas mesaĝon al la babilejo"
+
+msgid "%s changes your nickname"
+msgstr "%s ŝanĝas vian kromnomon"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s sendas mesaĝon al iu en la babilejo"
+
+msgid "%s changes the room topic"
+msgstr "%s ŝanĝas la babilejan subjekton"
+
+msgid "%s kicks an user of the room"
+msgstr "%s forpelas uzanton el la babilejo"
+
+msgid "%s bans an user of the room"
+msgstr "%s ekskludas uzanton el la babilejo"
+
+msgid "%s invites someone to join the room"
+msgstr "%s invitas iun por aliri la babilejon"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/es/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/es/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..94a7132
Binary files /dev/null and b/jappixmini/jappix/lang/es/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/es/LC_MESSAGES/main.po b/jappixmini/jappix/lang/es/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..b9a5714
--- /dev/null
@@ -0,0 +1,1870 @@
+# Spanish translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:27+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Javascript no se encuentra activado en tu navegador, de modo que no podrás poner en marcha Jappix! Por favor, corrige esto."
+
+msgid "An open social network"
+msgstr "Una red social abierta"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix ha sido interrumpido por un problema de red, un fallo o un acceso incorrecto (comprueba que has introducido las credenciales correctas). Lamentamos el inconveniente."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "¡No se pudo conseguir la lista de elementos de este servidor!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Tu contraseña ha sido cambiada, ahora puedes conectarte a tu cuenta con los nuevos datos de acceso."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Tu cuenta XMPP ha sido suprimida... ¡Adiós!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Ya saliste de tu cuenta de XMPP, ¡que disfrutes el resto del día!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "La sala a la que te has unido no existe. ¡La deberías crear primero!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "El grupo de charla ha sido eliminado, ahora culquiera puede volver a crearla."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "El usuario no se encuentra en esta sala."
+
+msgid "Please enter the group chat address to join."
+msgstr "Escribe el nombre de la sala donde quieres entrar."
+
+msgid "Please enter your nickname to join %s."
+msgstr "¿Qué apodo quieres tener en la sala %s?"
+
+msgid "This room (%s) is protected with a password."
+msgstr "La sala %s está protegida por una clave."
+
+msgid "Your browser is out of date!"
+msgstr "¡Necesita actualizar tu navegador!"
+
+msgid "Last %s version is better!"
+msgstr "¡La última versión de %s es mejor!"
+
+msgid "Login"
+msgstr "Acceder"
+
+msgid "Register"
+msgstr "Registrarse"
+
+msgid "Here we go!"
+msgstr "¡Allá vamos!"
+
+msgid "Server"
+msgstr "Servidor"
+
+msgid "Password"
+msgstr "Contraseña"
+
+msgid "Remember me"
+msgstr "Recordarme"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "No se puede usar esta herramienta porque no está activada."
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Debido a un problema de red, se le ha desconectado. ¿Qué quieres hacer ahora?"
+
+msgid "Reconnect"
+msgstr "Volver a conectar"
+
+msgid "Messages"
+msgstr "Mensajes"
+
+msgid "Profile"
+msgstr "Perfil"
+
+msgid "Options"
+msgstr "Opciones"
+
+msgid "Disconnect"
+msgstr "Desconectar"
+
+msgid "Filter"
+msgstr "Filtro"
+
+msgid "Add a friend"
+msgstr "Agregar a un amigo"
+
+msgid "Your groupchats"
+msgstr "Tus salas de conversación"
+
+msgid "Manage your favorite groupchats"
+msgstr "Gestiona tus grupos de chat favoritos"
+
+msgid "More stuff"
+msgstr "Más cosas"
+
+msgid "Show all friends"
+msgstr "Mostrar a todos los amigos"
+
+msgid "Only show connected friends"
+msgstr "Mostrar sólo a los amigos conectados"
+
+msgid "Message archives"
+msgstr "Archivos de mensajes"
+
+msgid "Date"
+msgstr "Fecha"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Selecciona el amigo con el cual quieres ver el historial de conversaciones"
+
+msgid "Nothing found for: %s"
+msgstr "Nada se encontró para: %s"
+
+msgid "A short message?"
+msgstr "¿Un mensaje corto?"
+
+msgid "How are you?"
+msgstr "¿Cómo estás?"
+
+msgid "What are you doing?"
+msgstr "¿Qué estás haciendo?"
+
+msgid "Join a chat"
+msgstr "Unirse al chat"
+
+msgid "Status"
+msgstr "Estado"
+
+msgid "Available"
+msgstr "Disponible"
+
+msgid "Talkative"
+msgstr "Hablador"
+
+msgid "Away"
+msgstr "Ausente"
+
+msgid "Not available"
+msgstr "No disponible"
+
+msgid "Busy"
+msgstr "Ocupado"
+
+msgid "Mood"
+msgstr "Humor"
+
+msgid "None"
+msgstr "Ninguno"
+
+msgid "Crazy"
+msgstr "Loco"
+
+msgid "Excited"
+msgstr "Excitado"
+
+msgid "Playful"
+msgstr "Juguetón"
+
+msgid "Happy"
+msgstr "Feliz"
+
+msgid "Shocked"
+msgstr "Conmocionado"
+
+msgid "Hot"
+msgstr "Caliente"
+
+msgid "Sad"
+msgstr "Triste"
+
+msgid "Amorous"
+msgstr "Amoroso"
+
+msgid "Confident"
+msgstr "Seguro"
+
+msgid "Activity"
+msgstr "Actividad"
+
+msgid "Chores"
+msgstr "Tareas"
+
+msgid "Drinking"
+msgstr "Bebiendo"
+
+msgid "Eating"
+msgstr "Comiendo"
+
+msgid "Exercising"
+msgstr "Haciendo ejercicio"
+
+msgid "Grooming"
+msgstr "Aseando"
+
+msgid "Appointment"
+msgstr "Cita"
+
+msgid "Inactive"
+msgstr "Inactivos"
+
+msgid "Relaxing"
+msgstr "Relajando"
+
+msgid "Talking"
+msgstr "Hablando"
+
+msgid "Traveling"
+msgstr "Viajando"
+
+msgid "Working"
+msgstr "Trabajando"
+
+msgid "View profile"
+msgstr "Ver el perfil"
+
+msgid "Repeat this notice"
+msgstr "Repetir este aviso"
+
+msgid "Remove this notice"
+msgstr "Eliminar este aviso"
+
+msgid "Your profile"
+msgstr "Tu perfil"
+
+msgid "Identity"
+msgstr "Identidad"
+
+msgid "Profile image"
+msgstr "Imagen del perfil"
+
+msgid "Others"
+msgstr "Otros"
+
+msgid "Personal"
+msgstr "Personal"
+
+msgid "Complete name"
+msgstr "Nombre completo"
+
+msgid "Nickname"
+msgstr "Apodo"
+
+msgid "First name"
+msgstr "Nombre"
+
+msgid "Last name"
+msgstr "Apellido"
+
+msgid "Date of birth"
+msgstr "Fecha de nacimiento"
+
+msgid "Contact"
+msgstr "Contacto"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Teléfono"
+
+msgid "Website"
+msgstr "Sitio web"
+
+msgid "Current"
+msgstr "Actual"
+
+msgid "Delete"
+msgstr "Borrar"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Qué pena, no tienes imagen en tu tarjeta de visita..."
+
+msgid "Address"
+msgstr "Dirección"
+
+msgid "Street"
+msgstr "Calle"
+
+msgid "City"
+msgstr "Ciudad"
+
+msgid "Postal code"
+msgstr "Código postal"
+
+msgid "Country"
+msgstr "País"
+
+msgid "Biography"
+msgstr "Biografía"
+
+msgid "Important notice"
+msgstr "Aviso importante"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Cuidado con la difusión de la información que le pongas a tu perfil: todo el mundo va a poder verla."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "No todo es privado en XMPP. Por ejemplo tu tarjeta de visita no lo es."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "Guardar"
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgid "Edit options"
+msgstr "Editar opciones"
+
+msgid "Channel"
+msgstr "Canal"
+
+msgid "Commands"
+msgstr "Comandos"
+
+msgid "Sounds"
+msgstr "Sonidos"
+
+msgid "Privacy"
+msgstr "Privacidad"
+
+msgid "Message archiving"
+msgstr "Archivado de mensajes"
+
+msgid "Store a history of your chats"
+msgstr "Guardar un historial de tus chats"
+
+msgid "Geolocation"
+msgstr "Geolocalización"
+
+msgid "Empty"
+msgstr "Vaciar"
+
+msgid "Empty channel"
+msgstr "Canal vacío"
+
+msgid "Persistent"
+msgstr "Persistente"
+
+msgid "Maximum notices"
+msgstr "Máximo de avisos"
+
+msgid "Account"
+msgstr "Cuenta"
+
+msgid "Change password"
+msgstr "Cambiar la contraseña"
+
+msgid "Delete account"
+msgstr "Eliminar cuenta"
+
+msgid "Old"
+msgstr "Antigua"
+
+msgid "New (2 times)"
+msgstr "Nueva (2 veces)"
+
+msgid "Continue"
+msgstr "Continuar"
+
+msgid "To"
+msgstr "A"
+
+msgid "Close"
+msgstr "Cerrar"
+
+msgid "unknown"
+msgstr "desconocido"
+
+msgid "Unavailable"
+msgstr "No disponible"
+
+msgid "is now"
+msgstr "es ahora"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr ""
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Ya está! Una nueva y bonita imagen en tu tarjeta de visita!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "No se maneja este tipo de imagen, o tal vez sea un problema de tamaño."
+
+msgid "Reply"
+msgstr "Responder"
+
+msgid "Error"
+msgstr "Error"
+
+msgid "Click here to solve the error"
+msgstr "Dale clic aquí para solucionar el problema"
+
+msgid "You"
+msgstr "Tú"
+
+msgid "Remove"
+msgstr "Eliminar"
+
+msgid "Rename"
+msgstr "Renombrar"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Hola, soy %s. Me gustaría tenerte como amigo en mi lista."
+
+msgid "Smiley insertion"
+msgstr "Inserción de emoticono"
+
+msgid "Change style"
+msgstr "Cambio de estilo"
+
+msgid "Text in bold"
+msgstr "Texto en negrita"
+
+msgid "Text in italic"
+msgstr "Texto en cursiva"
+
+msgid "Underlined text"
+msgstr "Texto subrayado"
+
+msgid "Save chat"
+msgstr "Chat guardado"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Haz click en el siguiente enlace para guardar la conversación, y espera un momento. Luego haz click de nuevo para descargar el archivo."
+
+msgid "This chat is empty!"
+msgstr "¡La sala está vacía!"
+
+msgid "Generate file!"
+msgstr "¡Generar archivo!"
+
+msgid "Download file!"
+msgstr "¡Bajar el archivo!"
+
+msgid "Clean current chat"
+msgstr "Limpieza del chat"
+
+msgid "View chat history"
+msgstr "Ver el historial del chat"
+
+msgid "Show user profile"
+msgstr "Visualizar el perfil del usuario"
+
+msgid "Add this contact to your friends"
+msgstr "Añadir a este contacto como amigo"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Añadir este grupo de chat a tus favoritos"
+
+msgid "All tabs"
+msgstr "Todas las pestañas"
+
+msgid "Close this tab"
+msgstr "Cerrar esta pestaña"
+
+msgid "no subject defined for this room."
+msgstr "no se especificó un tema para esta sala."
+
+msgid "Administration panel for this room"
+msgstr "Panel de administración de la sala"
+
+msgid "Moderators"
+msgstr "Moderadores"
+
+msgid "Participants"
+msgstr "Participantes"
+
+msgid "Visitors"
+msgstr "Visitantes"
+
+msgid "Manage favorite rooms"
+msgstr "Organiza tus salas favoritas"
+
+msgid "Change favorites"
+msgstr "Cambiar tus favoritos"
+
+msgid "Search a room"
+msgstr "Buscar una sala"
+
+msgid "Select a favorite"
+msgstr "Seleccionar un favorito"
+
+msgid "Getting the name..."
+msgstr "Consiguiendo el nombre..."
+
+msgid "Gateway"
+msgstr "Pasarela"
+
+msgid "Name"
+msgstr "Nombre"
+
+msgid "Room"
+msgstr "Sala"
+
+msgid "Add"
+msgstr "Añadir"
+
+msgid "Edit"
+msgstr "Editar"
+
+msgid "Search a room on"
+msgstr "Buscar una sala en"
+
+msgid "No room found on this server."
+msgstr "No se encontraron salas en este servidor."
+
+msgid "Service discovery"
+msgstr "Descubrir servicios"
+
+msgid "Server to query"
+msgstr "Servidor que consultar"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Esta entidad no mandó ningún resultado..."
+
+msgid "Accounts"
+msgstr "Cuentas"
+
+msgid "Authentications"
+msgstr "Autentificaciones"
+
+msgid "Automation"
+msgstr "Automatización"
+
+msgid "Clients"
+msgstr "Clientes"
+
+msgid "Collaboration"
+msgstr "Colaboración"
+
+msgid "Components"
+msgstr "Componentes"
+
+msgid "Rooms"
+msgstr "Salas"
+
+msgid "Directories"
+msgstr "Directorios"
+
+msgid "Gateways"
+msgstr "Pasarelas"
+
+msgid "News"
+msgstr "Noticias"
+
+msgid "Hierarchy"
+msgstr "Jerarquía"
+
+msgid "Proxies"
+msgstr "Servidores proxy"
+
+msgid "Publication/Subscription"
+msgstr "Publicación/Suscripción"
+
+msgid "Storage"
+msgstr "Almacenamiento"
+
+msgid "Service offline or broken"
+msgstr "Servidor fuera de línea o roto"
+
+msgid "Your inbox"
+msgstr "Tu bandeja de entrada"
+
+msgid "Available actions"
+msgstr "Acciones disponibles"
+
+msgid "Clean"
+msgstr "Limpiar"
+
+msgid "New"
+msgstr "Nuevo"
+
+msgid "Received"
+msgstr "Recibido"
+
+msgid "Subject"
+msgstr "Asunto"
+
+msgid "Content"
+msgstr "Contenido"
+
+msgid "Send message"
+msgstr "Enviar mensaje"
+
+msgid "Your inbox is empty."
+msgstr "Tu bandeja de entrada está vacía"
+
+msgid "MUC administration"
+msgstr "Administración de MUC"
+
+msgid "You administrate this room"
+msgstr "Tú administras esta sala"
+
+msgid "Enter new subject"
+msgstr "Introduce el nuevo asunto"
+
+msgid "Configuration"
+msgstr "Configuración"
+
+msgid "Authorizations"
+msgstr "Autorizaciones"
+
+msgid "Member list"
+msgstr "Lista de miembros"
+
+msgid "Owner list"
+msgstr "Lista de propietarios"
+
+msgid "Administrator list"
+msgstr "Lista de administradores"
+
+msgid "Outcast list"
+msgstr "Lista de rechazados"
+
+msgid "Add an input"
+msgstr "Añadir una entrada"
+
+msgid "Destroy this MUC"
+msgstr "Destruir este MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Sí, ¡hagámoslo!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Tu amigo está prestando atención a la conversación."
+
+msgid "Your friend is writing a message..."
+msgstr "Tu amigo está escribiendo un mensaje..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Tu amigo dejó de escribir un mensaje."
+
+msgid "Your friend is doing something else."
+msgstr "Tu amigo está haciendo otra cosa."
+
+msgid "Your friend closed the chat."
+msgstr "Tu amigo cerró el chat."
+
+msgid "Requesting this service..."
+msgstr "Solicitando este servicio..."
+
+msgid "Loading"
+msgstr "Cargando"
+
+msgid "joined the chat room"
+msgstr "se unió al chat"
+
+msgid "left the chat room"
+msgstr "ha dejado el chat"
+
+msgid "no status"
+msgstr "no tiene estado"
+
+msgid "has been kicked"
+msgstr "ha sido expulsado"
+
+msgid "has been banned"
+msgstr "ha sido prohibido"
+
+msgid "no reason"
+msgstr "ninguna razón"
+
+msgid "Communicate with the entire world!"
+msgstr "¡Comunícate con el mundo entero!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Te permite mantenerte en contacto con los millones de usuarios que en la actualidad usan la red XMPP como tú con Jappix. ¡Únete a la comunidad y sigue libre!"
+
+msgid "Hi there!"
+msgstr "¡Hola!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Bienvenida en %1s: “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Entra a tu cuenta de XMPP existente, o crea una nueva!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix es un proyecto de código abierto de PostPro, una organización sin ánimo de lucro que nos proporciona una gran ayuda."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Entra a tu cuenta de XMPP existente. También se puede usar el %s para entrar a una sala de charla."
+
+msgid "Previous"
+msgstr "Atrás"
+
+msgid "General"
+msgstr "General"
+
+msgid "Advanced"
+msgstr "Avanzado"
+
+msgid "Resource"
+msgstr "Recurso"
+
+msgid "Priority"
+msgstr "Prioridad"
+
+msgid "Low"
+msgstr "Bajo"
+
+msgid "Medium"
+msgstr "Medio"
+
+msgid "High"
+msgstr "Alto"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Introduce el grupo de chat al que deseas unirte y el nick que quieres tener. También puedes volver a la %s."
+
+msgid "login page"
+msgstr "Página de acceso"
+
+msgid "Share this link with your friends:"
+msgstr "Comparte este enlace con tus amigos"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Crea una nueva cuenta XMPP para unirte a tus amigos en vuestra propia nube social. ¡Es fácil!"
+
+msgid "Required"
+msgstr "Requerido"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Ya creaste tu cuenta, aquí viene tu dirección de XMPP:"
+
+msgid "Manager"
+msgstr "Gerente"
+
+msgid "Project"
+msgstr "Proyecto"
+
+msgid "Encrypted"
+msgstr "Encriptado"
+
+msgid "Unencrypted"
+msgstr "No cifrado."
+
+msgid "Where are you?"
+msgstr "¿Dónde estás?"
+
+msgid "What's up with you?"
+msgstr "¿Que pasa contigo?"
+
+msgid "Fetching the social channel..."
+msgstr "Consiguiendo el canal social..."
+
+msgid "You are synchronized with your network."
+msgstr "Estás sincronizadx con tu red."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "No puedes enviar nada: ¡solo puedes recibir avisos!"
+
+msgid "Media viewer"
+msgstr "Visor de medios"
+
+msgid "Browse"
+msgstr "Examinar"
+
+msgid "Command"
+msgstr "Comando"
+
+msgid "Subscribe"
+msgstr "Suscribirse"
+
+msgid "Join"
+msgstr "Unirse"
+
+msgid "Automatic"
+msgstr "Automático"
+
+msgid "Search"
+msgstr "Buscar"
+
+msgid "No result!"
+msgstr "¡Sin resultados!"
+
+msgid "No notifications."
+msgstr "Ninguna notificación."
+
+msgid "would like to add you as a friend."
+msgstr "le gustaría añadirte como amigo/a."
+
+msgid "would like you to join this chatroom:"
+msgstr "le gustaría que te unieras a esta sala:"
+
+msgid "Do you accept?"
+msgstr "¿Aceptas?"
+
+msgid "Yes"
+msgstr "Si"
+
+msgid "No"
+msgstr "No"
+
+msgid "would like to get authorization."
+msgstr "quisiera tener autorización de ver tu estado."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "¿Quiere ver las amistades que %s te sugiere?"
+
+msgid "Submit"
+msgstr "Enviar"
+
+msgid "Client"
+msgstr "Cliente"
+
+msgid "System"
+msgstr "Sistema"
+
+msgid "Local time"
+msgstr "Hora local"
+
+msgid "Comments"
+msgstr "Comentarios"
+
+msgid "User profile"
+msgstr "Perfil de usuaria/o"
+
+msgid "See his/her position on the globe"
+msgstr "Ver su ubicación el el mapa mundial"
+
+msgid "Confirm"
+msgstr "Confirmar"
+
+msgid "anonymous mode"
+msgstr "modo anónimo"
+
+msgid "Groups"
+msgstr "Grupos"
+
+msgid "Unclassified"
+msgstr "Sin clasificar"
+
+msgid "Authorize"
+msgstr "Autorizar"
+
+msgid "Ask for authorization"
+msgstr "Pedir autorización"
+
+msgid "Unblock"
+msgstr "Desbloquear"
+
+msgid "Prohibit"
+msgstr "Prohibir"
+
+msgid "Block"
+msgstr "Bloque"
+
+msgid "Chat"
+msgstr "Chat"
+
+msgid "Groupchat"
+msgstr "Chat en grupo"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Móvil"
+
+msgid "Desktop"
+msgstr "Escritorio"
+
+msgid "Mobile"
+msgstr "Móvil"
+
+msgid "Please wait..."
+msgstr "Por favor, espera..."
+
+msgid "Please enable JavaScript"
+msgstr "Por favor, habilita JavaScript"
+
+msgid "Your channel"
+msgstr "Tu canal"
+
+msgid "Channel of"
+msgstr "Canal de"
+
+msgid "More notices..."
+msgstr "Más avisos..."
+
+msgid "Attach a file"
+msgstr "Adjuntar un archivo"
+
+msgid "Send"
+msgstr "Enviar"
+
+msgid "Unattach the file"
+msgstr "Ya no adjuntar el archivo"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Hubo un error al tratar de enviar tu archivo: a lo mejor pesa demasiado (el máximo es %s), o está prohibido!"
+
+msgid "Authorization failed"
+msgstr "Falló la autorización"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Falló el registro, por favor, elije otro nombre de usuario"
+
+msgid "Service unavailable"
+msgstr "Servicio no disponible"
+
+msgid "Internal server error, try later"
+msgstr "Error interno del servidor, intentar más tarde"
+
+msgid "Your form has been sent."
+msgstr "Ya se envió tu formulario."
+
+msgid "Application"
+msgstr "Aplicación"
+
+msgid "XMPP links"
+msgstr "Enlaces XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Abrir enlaces XMPP con Jappix"
+
+msgid "changed the subject to:"
+msgstr "asunto cambiado a:"
+
+msgid "Welcome!"
+msgstr "¡Bienvenido!"
+
+msgid "Friends"
+msgstr "Amigos"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "¡Bienvenido a Jappix, tu propia nube social!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Antes de que lo empiezes a usar, tendrás que cambiar unos parametros, buscar a amigxs, y completar tu perfil."
+
+msgid "Enable notification sounds"
+msgstr "Habilitar notificación por sonidos"
+
+msgid "Share your position on the globe"
+msgstr "Comparte tu ubicación geográfica"
+
+msgid "Offline friends"
+msgstr "Amigos fuera de línea"
+
+msgid "Don't hide offline friends"
+msgstr "Que aparezcan mis amigos no conectados"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Usa esta herramienta para encontrar a tus amigos en el servidor que estás usando ahora mismo, o añádelos más tarde."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Muy bien! Ahora puedes compartir Jappix con tus amigxs!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Cuando uses el botón “Guardar”, el editor de perfil se abrirá. ¡Te deseamos buena socialización!"
+
+msgid "Share Jappix on %s"
+msgstr "Comparte Jappix en %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Soy %s, y estoy usando Jappix, una plataforma social abierta."
+
+msgid "Unknown name"
+msgstr "Nombre desconocido"
+
+msgid "Unknown country"
+msgstr "País desconocido"
+
+msgid "Click to enable"
+msgstr "Haz click para habilitar"
+
+msgid "Click to disable"
+msgstr "Haz click para deshabilitar"
+
+msgid "Installation"
+msgstr "Instalación"
+
+msgid "Jappix installation"
+msgstr "Instalación de Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "¡Bienvenido a la instalación de Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Esta herramienta te ayudará a instalar Jappix más rápidamente, la primera plataforma social con todas las funciones y basada en XMPP, en tu servidor. Ni siquiera necesitas conocimientos técnicos."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Vamos a ver los pasos de instalación:"
+
+msgid "Welcome"
+msgstr "Bienvenido"
+
+msgid "Storage configuration"
+msgstr "Configuración de almacenamiento"
+
+msgid "Administrator account"
+msgstr "Cuenta de administrador"
+
+msgid "Main configuration"
+msgstr "Configuración principal"
+
+msgid "Hosts configuration"
+msgstr "Configuración de los huéspedes"
+
+msgid "Services installation"
+msgstr "Instalación de servicios"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Si el idioma actual no coincide con el tuyo (%1s), puedes hacer que Jappix hable en %2s. Esta opción se guardará."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Si deseas obtener ayuda sobre la instalación y configuración de Jappix, puedes utilizar toda nuestra documentación, disponible en:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Es hora de construir nuestra propia nube social: ¡solo tienes que ir al siguiente paso! "
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix almacena información permanente (archivos compartidos, historial de conversaciones, su música, y la configuración) dentro de una carpeta segura."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix debe ser capaz de escribir en esta carpeta para crear sus sub-directorios. Si no es así, debes establecer los derechos a 1s% o cambiar el propietario de la carpeta a 2s% (dependiendo de tu configuración)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "La carpeta es escribible, ¡puedes continuar!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix te ofrece la posibilidad de gestionar tu configuración, instalar nuevos plugins y buscar actualizaciones. Por eso tienes que crear una cuenta de administración para acceder al gerente."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Cuando Jappix esté instalado, basta con hacer clic en el enlace de gerente en la página principal para acceder."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Uy, ¡se olvidó algo o las dos contraseñas no coinciden!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix necesita que especifiques algunos valores para trabajar. Por favor, corrije las siguientes entradas (o mantén los valores por defecto, que bastan para la mayoría de la gente)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Ten en cuenta que si no especificas un valor que es obligatorio, se completará automáticamente con la opción por defecto."
+
+msgid "User"
+msgstr "Usuario"
+
+msgid "Service"
+msgstr "Servicio"
+
+msgid "Service name"
+msgstr "Nombre del servicio"
+
+msgid "Service description"
+msgstr "Descripción del servicio"
+
+msgid "Connection"
+msgstr "Conexión"
+
+msgid "Lock the host"
+msgstr "Bloquear el anfitrión "
+
+msgid "Anonymous mode"
+msgstr "Modo anónimo"
+
+msgid "Registration allowed"
+msgstr "Permitir la creación de cuentas"
+
+msgid "Use a proxy"
+msgstr "Usar un proxy"
+
+msgid "Encryption"
+msgstr "Cifrado"
+
+msgid "HTTPS storage"
+msgstr "Almacenamiento con HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Forzar el uso de HTTPS"
+
+msgid "Compression"
+msgstr "Compresión"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Esta página te ayuda a especificar los hosts por defecto a los que Jappix se conectará. Puedes dejarlo como está y continuar si quieres usar los hosts oficiales del servicio."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Quizá no sepas lo que es un servidor BOSH. De hecho, hay un enlace entre un cliente Jappix y un servidor XMPP, que es necesario debido a limitaciones técnicas."
+
+msgid "Main host"
+msgstr "Host principal"
+
+msgid "Groupchat host"
+msgstr "Host de chat en grupo"
+
+msgid "Anonymous host"
+msgstr "Host anónimo"
+
+msgid "Directory host"
+msgstr "Host directorio"
+
+msgid "BOSH host"
+msgstr "Host BOSH"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Puedes instalar algunos programas adicionales en tu servidor, para ampliar las funciones de Jappix. Otros podrían ser modificados, debido a las restricciones de seguridad que se establecen de forma predeterminada."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Para realizar esto, debes poder acceder al shell de tu servidor e iniciar una sesión como root. Recuerda que esto es facultativo, Jappix funcionará sin estos módulos, pero algunas de sus características no estarán disponibles."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Después de terminar la instalación, Jappix generará los archivos de cache. Puede ser lento, sólo tienes que esperar hasta que se muestre la aplicación, sin presionar ningún botón."
+
+msgid "Thanks for using Jappix!"
+msgstr "¡Gracias por usar Jappix!"
+
+msgid "Next"
+msgstr "Siguiente"
+
+msgid "Finish"
+msgstr "Terminar"
+
+msgid "Check again"
+msgstr "Comprobar otra vez"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "La carpeta no tiene permisos de escritura, configura correctamente los permisos al directorio %s."
+
+msgid "%s is installed on your system."
+msgstr "%s está instalado en tu sistema."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s no está instalado en tu sistema, debes instalar %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "El peso máximo de envío que acepta PHP es suficiente (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "El peso máximo de envío que acepta PHP no es suficiente (%1s). Le deberías indicar un valor de %2s en el archivo %3s."
+
+msgid "Jappix manager"
+msgstr "Gerente de Jappix"
+
+msgid "Manager access"
+msgstr "Administrador de acceso"
+
+msgid "Statistics"
+msgstr "Estadísticas"
+
+msgid "Hosts"
+msgstr "Anfitriones"
+
+msgid "Design"
+msgstr "Diseño"
+
+msgid "Repeat"
+msgstr "Repita"
+
+msgid "All"
+msgstr "Todo"
+
+msgid "Horizontal"
+msgstr "Horizontal"
+
+msgid "Vertical"
+msgstr "Vertical"
+
+msgid "Center"
+msgstr "Centro"
+
+msgid "Left"
+msgstr "Izquierda"
+
+msgid "Right"
+msgstr "Derecha"
+
+msgid "Top"
+msgstr "Arriba"
+
+msgid "Bottom"
+msgstr "Abajo"
+
+msgid "Adapt"
+msgstr "Adaptar"
+
+msgid "Color"
+msgstr "Color"
+
+msgid "Users"
+msgstr "Usuarios"
+
+msgid "Updates"
+msgstr "Actualizaciones"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Ésta es un área restringida: sólo los usuarios autorizados pueden gestionar este nodo Jappix."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Por favor, utiliza el formulario de abajo para acceder al panel de administración."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Para mejorar la seguridad, las sesiones son limitadas en tiempo y cuando se cierre el navegador, la sesión se cerrará."
+
+msgid "Credentials"
+msgstr "Credenciales"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Se ha cerrado la sesión. ¡Adiós!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Uy, no ha sido posible reconocerte como administrador válido. Comprueba tus credenciales!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Las estadísticas básicas son procesadas por Jappix sobre algunas cosas importantes, Las puedes encontrar más abajo."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Modifica la configuración de tu nodo Jappix con esta herramienta"
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Con esta herramienta, modifica los anfitriones manejados por Jappix"
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Todos los archivos de almacenamiento dentro de Jappix se pueden organizar con esta herramienta: selecciona una carpeta para ir editando su contenido!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix es totalmente configurable: aquí se puede cambiar su diseño."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Ésta no es una imagen válida, por favor usa PNG, GIF o JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "La imagen no se pudo recibir. ¿Sería posible intentarlo nuevamente?"
+
+msgid "Your image was added to the list!"
+msgstr "¡Tu imagen se agregó a la lista!"
+
+msgid "Changes saved!"
+msgstr "Los cambios han sido guardados!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Se puede definir más de un administrador de Jappix. También se puede cambiar contraseñas."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Actualiza tu nodo de Jappix aquí, o revisa si existe alguna nueva versión. También aparece información sobre la versión más reciente (en inglés)."
+
+msgid "Access statistics"
+msgstr "Acceder a las estadísticas"
+
+msgid "Share statistics"
+msgstr "Compartir estadísticas"
+
+msgid "Other statistics"
+msgstr "Otras estadísticas"
+
+msgid "January"
+msgstr "Enero"
+
+msgid "February"
+msgstr "Febrero"
+
+msgid "March"
+msgstr "Marzo"
+
+msgid "April"
+msgstr "Abril"
+
+msgid "May"
+msgstr "Mayo"
+
+msgid "June"
+msgstr "Junio"
+
+msgid "July"
+msgstr "Julio"
+
+msgid "August"
+msgstr "Agosto"
+
+msgid "September"
+msgstr "Septiembre"
+
+msgid "October"
+msgstr "Octubre"
+
+msgid "November"
+msgstr "Noviembre"
+
+msgid "December"
+msgstr "Diciembre"
+
+msgid "Monday"
+msgstr "Lunes"
+
+msgid "Tuesday"
+msgstr "Martes"
+
+msgid "Wednesday"
+msgstr "Miércoles"
+
+msgid "Thursday"
+msgstr "Jueves"
+
+msgid "Friday"
+msgstr "Viernes"
+
+msgid "Saturday"
+msgstr "Sábado"
+
+msgid "Sunday"
+msgstr "Domingo"
+
+msgid "Total"
+msgstr "Total"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Registros"
+
+msgid "Music"
+msgstr "Música"
+
+msgid "Backgrounds"
+msgstr "Fondos de pantalla"
+
+msgid "Share"
+msgstr "Compartir"
+
+msgid "Background"
+msgstr "Fondo de pantalla"
+
+msgid "Notice"
+msgstr "Aviso"
+
+msgid "Your design preferences have been saved!"
+msgstr "¡Ya se guardaron tus preferencias de diseño!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Por favor comprueba los datos introducidos: ¡falta algo!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Aquí puedes cambiar el fondo de pantalla de Jappix. Puede ser el color que quieras, o una imagen. ¡Deja que tu creatividad fluya!"
+
+msgid "Use default background"
+msgstr "Usar el fondo de pantalla por defecto"
+
+msgid "Use your own image"
+msgstr "Usa tu propia imagen"
+
+msgid "Select a background to use and change the display options."
+msgstr "Seleccione un fondo para usar y modificar las opciones de visualización."
+
+msgid "Use your own color"
+msgstr "Usa tu propio color"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Escribe el valor en hexadecimal del color que deseas tener como fondo."
+
+msgid "Manage backgrounds"
+msgstr "Organizar los fondos de pantalla"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Aquí puedes agregarle imágenes de fondo a la lista. Gracias por enviar una imagen válida."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Si deseas quitar algunos fondos, utiliza el navegador a continuación."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Define un aviso de inicio que vean todxs lxs usuarixs. Puede ser una alerta, un mensaje importante, o una publicidad."
+
+msgid "Simple notice"
+msgstr "Aviso simple "
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Este aviso sólo necesita un texto simple para ser visualizado, pero no se permite código!"
+
+msgid "Advanced notice"
+msgstr "Aviso avanzado"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Puedes personalizar tu aviso con código HTML, CSS y Javascript, pero necesitarás programar el estilo."
+
+msgid "Available updates"
+msgstr "Actualizaciones disponibles"
+
+msgid "What's new?"
+msgstr "¿Qué hay de nuevo?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "No se puede escribir en tu carpeta de almacenamiento. Gracias por otorgarle al servidor los permisos adecuados."
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s le puede causar problemas al proxy. Por favor, sube el valor de %2s a %3s."
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Estas utilizando una versión de desarrollo de Jappix. Actualizala con nuestro repositorio ejecutando: %s"
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Una nueva versión de Jappix está disponible! Comprueba las novedades y ejecuta la actualización!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Esta versión ya no es la más reciente. Actualízala ahora a %s haciendo clic aquí!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Esta versión parece ser la más reciente, pero todavía puedes buscar actualizaciones manualmente con este enlace."
+
+msgid "Check for updates"
+msgstr "Buscar actualizaciones"
+
+msgid "Update in progress"
+msgstr "Actualización en curso"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix ha sido actualizado: ahora estás ejecutando la última versión. Que te diviertas!"
+
+msgid "The update has failed! Please try again later."
+msgstr "La actualización ha fallado! Por favor, inténtalo nuevamente más tarde."
+
+msgid "Downloading package..."
+msgstr "Descargando el paquete..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Eliminación de archivos del sistema actual de Jappix ..."
+
+msgid "Extracting package..."
+msgstr "Extrayendo el paquete..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Generando otra vez la jerarquía de almacenamiento..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix está actualizado!"
+
+msgid "Aborted: socket error!"
+msgstr "Abortada: error de socket!"
+
+msgid "Aborted: buffer error!"
+msgstr "Abortada: Error de buffer!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Abortada: faltan algunos permisos de escritura!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Abortado: no se pudo extraer el paquete!"
+
+msgid "Visits"
+msgstr "Visitas"
+
+msgid "Daily"
+msgstr "Diario"
+
+msgid "Weekly"
+msgstr "Semanal"
+
+msgid "Monthly"
+msgstr "Mensual"
+
+msgid "Yearly"
+msgstr "Anual"
+
+msgid "Size"
+msgstr "Tamaño"
+
+msgid "Clean everything"
+msgstr "Limpiar todo"
+
+msgid "Purge cache"
+msgstr "Purgar caché"
+
+msgid "Purge logs"
+msgstr "Purgar registros"
+
+msgid "Purge updates"
+msgstr "Purgar actualizaciones"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "La carpeta de almacenamiento que querías limpiar está vacía ahora!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Mantén tu nodo de Jappix fresco y dinámico, limpiando las carpetas de almacenamiento regularmente!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Carga tu música (Ogg Vorbis, MP3 o WAV) para poder escucharla en Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "El archivo que quieres subir tiene que pesar menos de %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Aquí puedes quedarte al tanto de lo que tus usuarios guarden en el servidor, y quitarle cualquier contenido no deseable."
+
+msgid "Title"
+msgstr "Título"
+
+msgid "Artist"
+msgstr "Artista"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Archivo"
+
+msgid "Upload"
+msgstr "Cargar"
+
+msgid "The folder is empty."
+msgstr "La carpeta está vacía."
+
+msgid "The music could not be received, please retry!"
+msgstr "La música no se pudo recibir, por favor intenta otra vez!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Éste no es un archivo de música válida. Por favor, ¡codifícalo en formato Ogg Vorbis, MP3 o WAV!"
+
+msgid "Your music has been added!"
+msgstr "¡Ya se agregó tu música!"
+
+msgid "The selected elements have been removed."
+msgstr "Los elementos seleccionados han sido suprimidos."
+
+msgid "You must select elements to remove!"
+msgstr "Debes seleccionar elementos que quitar!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Aquí puedes agregar un nuevo usuario, o cambiar contraseñas (introduce un nombre de usuario existente). Por favor, ¡usa una contraseña fuerte!"
+
+msgid "Manage"
+msgstr "Administrar"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Aquí se pueden quitar usuarios. El último que quede no se puede quitar."
+
+msgid "The user has been added!"
+msgstr "El usuario ha sido agregado!"
+
+msgid "The chosen users have been removed."
+msgstr "Los usuarios seleccionados han sido suprimidos"
+
+msgid "You must select one or more users to be removed!"
+msgstr "Debes seleccionar por lo menos un usuario que quitar!"
+
+msgid "Yesterday"
+msgstr "Ayer"
+
+msgid "%s days ago"
+msgstr "hace %s días"
+
+msgid "User currently active"
+msgstr "Usuario activo actualmente"
+
+msgid "Last seen: %s"
+msgstr "Se vió por última vez: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inactivo desde: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Parece que tu amigo no recibió el mensaje!"
+
+msgid "Static content server"
+msgstr "Servidor de contenido estático"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Éste es el servidor de contenido estático para %1s: “%2s”."
+
+msgid "Suggested friends"
+msgstr "Amistades recomendadas"
+
+msgid "Check all"
+msgstr "Activar todo"
+
+msgid "Uncheck all"
+msgstr "Deactivar todo"
+
+msgid "Choose"
+msgstr "Escoga"
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr "Permitir"
+
+msgid "Deny"
+msgstr "prohibir"
+
+msgid "Group"
+msgstr "Grupo"
+
+msgid "Subscription"
+msgstr "suscripción"
+
+msgid "Both"
+msgstr "Ambos"
+
+msgid "From"
+msgstr "De"
+
+msgid "Everybody"
+msgstr "Todo el mundo"
+
+msgid "Send messages"
+msgstr "Enviar mensajes"
+
+msgid "Send queries"
+msgstr "Enviar peticiones"
+
+msgid "See my status"
+msgstr "Ver mi estado"
+
+msgid "Send his/her status"
+msgstr "Enviar su estado"
+
+msgid "Everything"
+msgstr "Todo"
+
+msgid "Item"
+msgstr "Artículo"
+
+msgid "Order"
+msgstr "Orden"
+
+msgid "Active for this session"
+msgstr "Activo en esta sesión"
+
+msgid "Always active"
+msgstr "Siempre activo"
+
+msgid "User directory"
+msgstr "Directorio del usuario"
+
+msgid "Search a friend"
+msgstr "Buscar a un amigo"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix es una plataforma social sin ánimo de lucro que se puede acceder en cualquier lugar, cualquier momento y comunicarse con quien desees."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/et/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/et/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..3344588
Binary files /dev/null and b/jappixmini/jappix/lang/et/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/et/LC_MESSAGES/main.po b/jappixmini/jappix/lang/et/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..f91ace4
--- /dev/null
@@ -0,0 +1,1870 @@
+# Estonian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Teie brauseris puudub JavaScript, mis tähendab seda et teil ei ole võimalik Jappixit käivitada! Palun parandage see."
+
+msgid "An open social network"
+msgstr "Avatud sotsiaalvõrgustik"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappixi töö on katkestatud võrgu tõrke, halva sisselogimise või mõne muu vea tõttu (kontrollige, et sisestasite õiged andmed), vabandame ebameeldivuste pärast."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Selle serveri elemendi nimekirja polnud võimalik omandada."
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Teie parool on muudetud, Te saate taas sisse logida kasutades uusi andmeid."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Teie XMPP konto on eemaldatud, hüvasti!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Te olete oma XMPP kontost välja logitud, head päeva!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Ruum millega Te liituda proovisite ei eksisteeri. Proovige see ise teha!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Grupivestlus on eemaldatud, nüüd saab keegi teine selle uuesti luua."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Kasutaja, kellega te püüate ühendust saada, ei eksisteeri enam selles ruumis."
+
+msgid "Please enter the group chat address to join."
+msgstr "Palun sisestage grupivestluse aadress millega liituda."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Palun sisestage oma hüüdnimi, et liituda %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Ruum (%s) on parooliga kaitstud."
+
+msgid "Your browser is out of date!"
+msgstr "Teil on liiga vana brauser!"
+
+msgid "Last %s version is better!"
+msgstr "Viimane versioon %s on parem!"
+
+msgid "Login"
+msgstr "Sisse logimine"
+
+msgid "Register"
+msgstr "Registreerimine"
+
+msgid "Here we go!"
+msgstr "Läks!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Parool"
+
+msgid "Remember me"
+msgstr "Jäta mind meelde"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "See tööriist on keelatud, Te ei saa seda kasutada!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Võrgu tõrke tõttu katkes ühendus serveriga. Mida te järgmiseks teha soovite?"
+
+msgid "Reconnect"
+msgstr "Taasühendus"
+
+msgid "Messages"
+msgstr "Sõnumid"
+
+msgid "Profile"
+msgstr "Profiil"
+
+msgid "Options"
+msgstr "Valikud"
+
+msgid "Disconnect"
+msgstr "Katkesta ühendus"
+
+msgid "Filter"
+msgstr "Filter"
+
+msgid "Add a friend"
+msgstr "Lisa kontakt"
+
+msgid "Your groupchats"
+msgstr "Minu grupivestlused"
+
+msgid "Manage your favorite groupchats"
+msgstr "Halda oma lemmikuid grupivestluseid"
+
+msgid "More stuff"
+msgstr "Rohkem asju"
+
+msgid "Show all friends"
+msgstr "Näita kõiki sõpru"
+
+msgid "Only show connected friends"
+msgstr "Näita ainult sisselogitud sõpru"
+
+msgid "Message archives"
+msgstr "Sõnumite arhiiv"
+
+msgid "Date"
+msgstr "Kuupäev"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Palun valige kontakt, et näha vestluse ajalugu."
+
+msgid "Nothing found for: %s"
+msgstr "Midagi ei leitud: %s"
+
+msgid "A short message?"
+msgstr "Lühisõnum?"
+
+msgid "How are you?"
+msgstr "Kuidas läheb?"
+
+msgid "What are you doing?"
+msgstr "Mida sa teed?"
+
+msgid "Join a chat"
+msgstr "Liitu vestlusega"
+
+msgid "Status"
+msgstr "Staatus"
+
+msgid "Available"
+msgstr "Saadaval"
+
+msgid "Talkative"
+msgstr "Jutukas"
+
+msgid "Away"
+msgstr "Eemal"
+
+msgid "Not available"
+msgstr "Mitte saadaval"
+
+msgid "Busy"
+msgstr "Hõivatud"
+
+msgid "Mood"
+msgstr "Meeleolu"
+
+msgid "None"
+msgstr "Midagi"
+
+msgid "Crazy"
+msgstr "Pöörane"
+
+msgid "Excited"
+msgstr "Elevil"
+
+msgid "Playful"
+msgstr "Vallatu"
+
+msgid "Happy"
+msgstr "Õnnelik"
+
+msgid "Shocked"
+msgstr "Šokeeritud"
+
+msgid "Hot"
+msgstr "Kuum"
+
+msgid "Sad"
+msgstr "Kurb"
+
+msgid "Amorous"
+msgstr "Armunud"
+
+msgid "Confident"
+msgstr "Enesekindel"
+
+msgid "Activity"
+msgstr "Tegevus"
+
+msgid "Chores"
+msgstr "Tööd"
+
+msgid "Drinking"
+msgstr "Joomine"
+
+msgid "Eating"
+msgstr "Söömine"
+
+msgid "Exercising"
+msgstr "Sportimine"
+
+msgid "Grooming"
+msgstr "Hooldamine"
+
+msgid "Appointment"
+msgstr "Kohtumine"
+
+msgid "Inactive"
+msgstr "Tegevusetu"
+
+msgid "Relaxing"
+msgstr "Lõõgastumine"
+
+msgid "Talking"
+msgstr "Rääkimine"
+
+msgid "Traveling"
+msgstr "Reisimine"
+
+msgid "Working"
+msgstr "Töötamine"
+
+msgid "View profile"
+msgstr "Vaata profiili"
+
+msgid "Repeat this notice"
+msgstr "Korda seda teadet"
+
+msgid "Remove this notice"
+msgstr "Eemalda see teade"
+
+msgid "Your profile"
+msgstr "Sinu profiil"
+
+msgid "Identity"
+msgstr "Identiteet"
+
+msgid "Profile image"
+msgstr "Profiili pilt"
+
+msgid "Others"
+msgstr "Muu"
+
+msgid "Personal"
+msgstr "Personaalne"
+
+msgid "Complete name"
+msgstr "Täisnimi"
+
+msgid "Nickname"
+msgstr "Hüüdnimi"
+
+msgid "First name"
+msgstr "Eesnimi"
+
+msgid "Last name"
+msgstr "Perekonnanimi"
+
+msgid "Date of birth"
+msgstr "Sünniaeg"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefon"
+
+msgid "Website"
+msgstr "Koduleht"
+
+msgid "Current"
+msgstr "Praegune"
+
+msgid "Delete"
+msgstr "Kustuta"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Kui kahju! Teil ei ole oma identiteedi kaardil profiili pilti!"
+
+msgid "Address"
+msgstr "Aadress"
+
+msgid "Street"
+msgstr "Tänav"
+
+msgid "City"
+msgstr "Linn"
+
+msgid "Postal code"
+msgstr "Postiindeks"
+
+msgid "Country"
+msgstr "Riik"
+
+msgid "Biography"
+msgstr "Elulugu"
+
+msgid "Important notice"
+msgstr "Oluline teave"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Olge ettevaatlik millist infot Te oma profiili alla lisate, sest seda võidakse kergesti näha teiste kasutajate poolt (isegi nende poolt keda Te ei soovi)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Mitte kõik pole XMPP's privaatne, see siin on üks nendest asjadest, teie avalik profiil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "On soovitatav üles laadida enda profiili pilt (%s maximum), sest see muudab Teid paremini äratuntavaks."
+
+msgid "Save"
+msgstr "Salvesta"
+
+msgid "Cancel"
+msgstr "Tühista"
+
+msgid "Edit options"
+msgstr "Muuda valikuid"
+
+msgid "Channel"
+msgstr "Kanal"
+
+msgid "Commands"
+msgstr "Käsud"
+
+msgid "Sounds"
+msgstr "Helid"
+
+msgid "Privacy"
+msgstr "Privaatsus"
+
+msgid "Message archiving"
+msgstr "Sõnumite arhiveerimine"
+
+msgid "Store a history of your chats"
+msgstr "Salvesta oma vestlused"
+
+msgid "Geolocation"
+msgstr "Geolokatsioon"
+
+msgid "Empty"
+msgstr "Tühi"
+
+msgid "Empty channel"
+msgstr "Tühi kanal"
+
+msgid "Persistent"
+msgstr "Püsiv"
+
+msgid "Maximum notices"
+msgstr "Maksimaalsed teavitused"
+
+msgid "Account"
+msgstr "Konto"
+
+msgid "Change password"
+msgstr "Muuda parool"
+
+msgid "Delete account"
+msgstr "Kustuta konto"
+
+msgid "Old"
+msgstr "Vana"
+
+msgid "New (2 times)"
+msgstr "Uus"
+
+msgid "Continue"
+msgstr "Jätka"
+
+msgid "To"
+msgstr "Kellele"
+
+msgid "Close"
+msgstr "Sulge"
+
+msgid "unknown"
+msgstr "tundmatu"
+
+msgid "Unavailable"
+msgstr "Mitte saadaval"
+
+msgid "is now"
+msgstr "on nüüd"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Palun oodake kuni Teie pilt on üles laetud..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Siin see on! Uus ilus profiili pilt"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Pildi formaat ei ole toetatud või on suurus mitte sobiv."
+
+msgid "Reply"
+msgstr "Vasta"
+
+msgid "Error"
+msgstr "Viga"
+
+msgid "Click here to solve the error"
+msgstr "Kliki siia, et viga lahendada"
+
+msgid "You"
+msgstr "Teie"
+
+msgid "Remove"
+msgstr "Eemalda"
+
+msgid "Rename"
+msgstr "Nimeta ümber"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Tere, ma olen %s, Ma sooviksin Teid endale sõbraks lisada."
+
+msgid "Smiley insertion"
+msgstr "Smaili sisestamine"
+
+msgid "Change style"
+msgstr "Muuda stiili"
+
+msgid "Text in bold"
+msgstr "Tekst paksult"
+
+msgid "Text in italic"
+msgstr "Tekst kaldkirjas"
+
+msgid "Underlined text"
+msgstr "Tekst allajoonitult"
+
+msgid "Save chat"
+msgstr "Salvesta vestlus"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Vajutage järgnevale lingile ja oodake, et saada vestluslogi. Seejärel klikkige uuesti, et saada fail."
+
+msgid "This chat is empty!"
+msgstr "See vestlus on tühi!"
+
+msgid "Generate file!"
+msgstr "Genereeri fail!"
+
+msgid "Download file!"
+msgstr "Lae fail alla!"
+
+msgid "Clean current chat"
+msgstr "Puhasta hetkeline vestlus"
+
+msgid "View chat history"
+msgstr "Vaata vestluse ajalugu"
+
+msgid "Show user profile"
+msgstr "Näita kasutaja profiili"
+
+msgid "Add this contact to your friends"
+msgstr "Lisa see kontakt oma kontakti nimekirja"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Lisa see grupivestlus oma lemmikutesse"
+
+msgid "All tabs"
+msgstr "Kõik kaardid"
+
+msgid "Close this tab"
+msgstr "Sulge see kaart"
+
+msgid "no subject defined for this room."
+msgstr "sellele ruumile ei ole teemat pandud"
+
+msgid "Administration panel for this room"
+msgstr "Selle ruumi administratsiooni paneel"
+
+msgid "Moderators"
+msgstr "Moderaatorid"
+
+msgid "Participants"
+msgstr "Osalejad"
+
+msgid "Visitors"
+msgstr "Külastajad"
+
+msgid "Manage favorite rooms"
+msgstr "Halda lemmik ruume"
+
+msgid "Change favorites"
+msgstr "Muuda lemmikuid"
+
+msgid "Search a room"
+msgstr "Otsi ruumi"
+
+msgid "Select a favorite"
+msgstr "Vali lemmik"
+
+msgid "Getting the name..."
+msgstr "Hangin nime..."
+
+msgid "Gateway"
+msgstr "Värav"
+
+msgid "Name"
+msgstr "Nimi"
+
+msgid "Room"
+msgstr "Ruum"
+
+msgid "Add"
+msgstr "Lisa"
+
+msgid "Edit"
+msgstr "Muuda"
+
+msgid "Search a room on"
+msgstr "Otsi ruumi"
+
+msgid "No room found on this server."
+msgstr "Ruumi ei leitud sellest serverist."
+
+msgid "Service discovery"
+msgstr "Teenuse avastamine"
+
+msgid "Server to query"
+msgstr "Serveri päring"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Vabandame, aga tulemusi ei leitud!"
+
+msgid "Accounts"
+msgstr "Kontod"
+
+msgid "Authentications"
+msgstr "Autentimised"
+
+msgid "Automation"
+msgstr "Automaatika"
+
+msgid "Clients"
+msgstr "Kliendid"
+
+msgid "Collaboration"
+msgstr "Koostöö"
+
+msgid "Components"
+msgstr "Komponendid"
+
+msgid "Rooms"
+msgstr "Ruumid"
+
+msgid "Directories"
+msgstr "Kataloogid"
+
+msgid "Gateways"
+msgstr "Väravad"
+
+msgid "News"
+msgstr "Uudised"
+
+msgid "Hierarchy"
+msgstr "Hierarhia"
+
+msgid "Proxies"
+msgstr "Proksid"
+
+msgid "Publication/Subscription"
+msgstr "Avalikustamine/Tellimus"
+
+msgid "Storage"
+msgstr "Hoiuruum"
+
+msgid "Service offline or broken"
+msgstr "Teenus lahti ühendatud või katki"
+
+msgid "Your inbox"
+msgstr "Teie postkast"
+
+msgid "Available actions"
+msgstr "Saadaval valikud"
+
+msgid "Clean"
+msgstr "Puhasta"
+
+msgid "New"
+msgstr "Uus"
+
+msgid "Received"
+msgstr "Vastu võetud"
+
+msgid "Subject"
+msgstr "Teema"
+
+msgid "Content"
+msgstr "Sisu"
+
+msgid "Send message"
+msgstr "Saada sõnum"
+
+msgid "Your inbox is empty."
+msgstr "Teie postkast on tühi."
+
+msgid "MUC administration"
+msgstr "MUC administratsioon"
+
+msgid "You administrate this room"
+msgstr "Teie olete ruumi administraator"
+
+msgid "Enter new subject"
+msgstr "Sisestage uus teema"
+
+msgid "Configuration"
+msgstr "Seadistus"
+
+msgid "Authorizations"
+msgstr "Load"
+
+msgid "Member list"
+msgstr "Liikmete nimekiri"
+
+msgid "Owner list"
+msgstr "Omanike nimekiri"
+
+msgid "Administrator list"
+msgstr "Administraatorite nimekiri"
+
+msgid "Outcast list"
+msgstr "Hüljatute nimekiri"
+
+msgid "Add an input"
+msgstr "Lisa sisend"
+
+msgid "Destroy this MUC"
+msgstr "Hävita see MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Jah, teeme seda!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Teie sõber jälgib vestlust."
+
+msgid "Your friend is writing a message..."
+msgstr "Teie sõber kirjutab..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Teie sõber lõpetas kirjutamise."
+
+msgid "Your friend is doing something else."
+msgstr "Teie sõber teeb midagi muud."
+
+msgid "Your friend closed the chat."
+msgstr "Teie sõber sulges vestluse."
+
+msgid "Requesting this service..."
+msgstr "Pärin seda teenust..."
+
+msgid "Loading"
+msgstr "Laen"
+
+msgid "joined the chat room"
+msgstr "liitus jututoaga"
+
+msgid "left the chat room"
+msgstr "lahkus jututoast"
+
+msgid "no status"
+msgstr "staatus puudub"
+
+msgid "has been kicked"
+msgstr "on välja visatud"
+
+msgid "has been banned"
+msgstr "on keelu alla pandud"
+
+msgid "no reason"
+msgstr "põhjust pole"
+
+msgid "Communicate with the entire world!"
+msgstr "Suhtle terve maailmaga!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "See lubab Teil miljonite inimestega kontakteeruda kes kasutavad XMPP võrgustikku nagu Teie kasutate Jappix'it. Liitu sõpruskonnaga ja ole vaba!"
+
+msgid "Hi there!"
+msgstr "Tere!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Tere tulemast %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Logi sisse enda XMPP kontole või tee tasuta uus!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix on avatud lähtekoodiga projekt PostPro'lt, mittetulundusühingult kes pakub meile suurt abi."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Logige sisse oma XMPP kontole. Te saate kasutada ka %s et liituda grupivestlusega."
+
+msgid "Previous"
+msgstr "Eelmine"
+
+msgid "General"
+msgstr "Üldine"
+
+msgid "Advanced"
+msgstr "Muud"
+
+msgid "Resource"
+msgstr "Vahend"
+
+msgid "Priority"
+msgstr "Eelis"
+
+msgid "Low"
+msgstr "Madal"
+
+msgid "Medium"
+msgstr "Keskmine"
+
+msgid "High"
+msgstr "Kõrge"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Sisestage grupivestlus millega soovite liituda ja oma hüüdnimi. Te saate ka alati minna tagasi %s."
+
+msgid "login page"
+msgstr "sisselogimise leht"
+
+msgid "Share this link with your friends:"
+msgstr "Jaga seda linki oma sõpradega:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Registreeri uus XMPP konto ja liitu oma sõpradega. See on lihtne!"
+
+msgid "Required"
+msgstr "Kohustuslik"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Te olete registreeritud, siin on Teie XMPP aadress:"
+
+msgid "Manager"
+msgstr "Haldur"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Krüpteeritud"
+
+msgid "Unencrypted"
+msgstr "Krüpteerimata"
+
+msgid "Where are you?"
+msgstr "Kus Te olete?"
+
+msgid "What's up with you?"
+msgstr "Mis toimub?"
+
+msgid "Fetching the social channel..."
+msgstr "Püüan kanalit..."
+
+msgid "You are synchronized with your network."
+msgstr "Te olete oma võrguga sünkroniseeritud."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Ei saa midagi saata: te saate ainult teateid vastu võtta!"
+
+msgid "Media viewer"
+msgstr "Meedia vaatur"
+
+msgid "Browse"
+msgstr "Brausi"
+
+msgid "Command"
+msgstr "Käsk"
+
+msgid "Subscribe"
+msgstr "Telli"
+
+msgid "Join"
+msgstr "Liitu"
+
+msgid "Automatic"
+msgstr "Automaatne"
+
+msgid "Search"
+msgstr "Otsi"
+
+msgid "No result!"
+msgstr "Ühtegi tulemust!"
+
+msgid "No notifications."
+msgstr "Pole teateid."
+
+msgid "would like to add you as a friend."
+msgstr "soovib lisada Teid sõbraks."
+
+msgid "would like you to join this chatroom:"
+msgstr "soovib kutsuda Teid sellesse jututuppa:"
+
+msgid "Do you accept?"
+msgstr "Kas Te olete nõus?"
+
+msgid "Yes"
+msgstr "Jah"
+
+msgid "No"
+msgstr "Ei"
+
+msgid "would like to get authorization."
+msgstr "soovib saada luba."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Kas Te soovite näha mida sõbra %s Teile soovitab?"
+
+msgid "Submit"
+msgstr "Kinnita"
+
+msgid "Client"
+msgstr "Klient"
+
+msgid "System"
+msgstr "Süsteem"
+
+msgid "Local time"
+msgstr "Kohalik aeg"
+
+msgid "Comments"
+msgstr "Kommentaarid"
+
+msgid "User profile"
+msgstr "Kasutaja profiil"
+
+msgid "See his/her position on the globe"
+msgstr "Vaata tema asukohta kaardil"
+
+msgid "Confirm"
+msgstr "Kinnita"
+
+msgid "anonymous mode"
+msgstr "anonüümne režiim"
+
+msgid "Groups"
+msgstr "Grupid"
+
+msgid "Unclassified"
+msgstr "Liigitamata"
+
+msgid "Authorize"
+msgstr "Autoriseeri"
+
+msgid "Ask for authorization"
+msgstr "Küsi autoriseerimist"
+
+msgid "Unblock"
+msgstr "Deblokeeri"
+
+msgid "Prohibit"
+msgstr "Keela"
+
+msgid "Block"
+msgstr "Blokeeri"
+
+msgid "Chat"
+msgstr "Vestlus"
+
+msgid "Groupchat"
+msgstr "Grupivestlus"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobiilis"
+
+msgid "Desktop"
+msgstr "Pealeht"
+
+msgid "Mobile"
+msgstr "Mobiil"
+
+msgid "Please wait..."
+msgstr "Palun oodake..."
+
+msgid "Please enable JavaScript"
+msgstr "Palun lubage JavaScript"
+
+msgid "Your channel"
+msgstr "Teie kanal"
+
+msgid "Channel of"
+msgstr "Kanal kuulub"
+
+msgid "More notices..."
+msgstr "Rohkem teateid..."
+
+msgid "Attach a file"
+msgstr "Lisa fail"
+
+msgid "Send"
+msgstr "Saada"
+
+msgid "Unattach the file"
+msgstr "Eemalda fail"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Faili üleslaadimisel tekkis viga: äkki on see liiga suur (%s maximum) või keelatud!"
+
+msgid "Authorization failed"
+msgstr "Autoriseerimine ebaõnnestus"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registreerimine ebaõnnestus, palun valige teine kasutajanimi"
+
+msgid "Service unavailable"
+msgstr "Teenus mitte saadaval"
+
+msgid "Internal server error, try later"
+msgstr "Serverisisene viga, proovige hiljem uuesti"
+
+msgid "Your form has been sent."
+msgstr "Teie ankeet on saadetud."
+
+msgid "Application"
+msgstr "Aplikatsioon"
+
+msgid "XMPP links"
+msgstr "XMPP lingid"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Ava XMPP lingid Jappix'iga"
+
+msgid "changed the subject to:"
+msgstr "muutis teema:"
+
+msgid "Welcome!"
+msgstr "Tere tulemast!"
+
+msgid "Friends"
+msgstr "Sõbrad"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Tere tulemast Jappix'isse, Teie isiklik sotsiaalvõrgustik!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Enne kui Te seda kasutama hakkate, peate te mõned seaded salvestama, otsima sõpru ja täitma oma profiili."
+
+msgid "Enable notification sounds"
+msgstr "Võimalda teadete helid"
+
+msgid "Share your position on the globe"
+msgstr "Jaga oma asukohta kaardil"
+
+msgid "Offline friends"
+msgstr "Ühenduseta sõbrad"
+
+msgid "Don't hide offline friends"
+msgstr "Ära peida ühenduseta sõpru"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Kasuta seda tööriista, et leida oma sõpru serverist või lisa nad hiljem."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Hea töö! Nüüd saate te Jappix'it sõpradega jagada!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Kui te vajutate salvestamise nuppu siis avaneb profiili muutmise aken."
+
+msgid "Share Jappix on %s"
+msgstr "Jaga Jappix'it %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Kasutan Jappix'it, avatud sotsiaalvõrgustik. Ma olen %s!"
+
+msgid "Unknown name"
+msgstr "Tundmatu nimi"
+
+msgid "Unknown country"
+msgstr "Tundmatu riik"
+
+msgid "Click to enable"
+msgstr "Kliki, et võimaldada"
+
+msgid "Click to disable"
+msgstr "Kliki, et keelata"
+
+msgid "Installation"
+msgstr "Paigaldus"
+
+msgid "Jappix installation"
+msgstr "jappixi paigaldus"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Tere tulemast Jappixi paigaldajasse!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "See tööriist aitab Teil kiiresti paigaldada Jappixi, avatud sotsiaalvõrgustiku, Teie serverisse. Teil ei ole isegi vaja tehnilist taipu."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Vaatame paigalduse samme:"
+
+msgid "Welcome"
+msgstr "Tere tulemast"
+
+msgid "Storage configuration"
+msgstr "Hoiuruumi konfiguratsioon"
+
+msgid "Administrator account"
+msgstr "Administraatori konto"
+
+msgid "Main configuration"
+msgstr "Põhiline konfiguratsioon"
+
+msgid "Hosts configuration"
+msgstr "Hosti konfiguratsioon"
+
+msgid "Services installation"
+msgstr "Teenuste paigaldus"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Kui hetkeline keel (%1s) ei kattu teie omaga siis saate muuta keele %2s."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Kui te soovite abi Jappixi paigalduse kohta siis Te võite vaadata tervet dokumentatsiooni, mis on saadaval:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "On aeg paigaldada Teie enda isiklik avatud sotsiaalvõrgustik: Minge järgmise sammu juurde!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix hoiab säilivaid andmeid (nagu nt jagatud failid, vestluse logid, Teie muusika ja konfiguratsioon) ühes ainsas turvatud kataloogis."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappixil peab olema siia ja alamkataloogidesse kirjutusõigus. Kui see puudub siis peate Te muutma õigused %1s või muutma kataloogi omaniku %2s (olenevalt Teie konfiguratsioonist)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Kataloogil on kirjutusõigused, Te võite jätkata!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix pakub võimalust hallata oma konfiguratsiooni, installida uusi pluginaid või otsida uuendusi. Sellepärast peate te tegema administraatori konto, et haldus lehele ligi pääseda."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Kui Jappix on paigaldatud siis lihtsalt vajutage Haldaja lingile avalehel, et sellele ligi pääseda."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Tundub, et Teil jäi midagi märkamata või need kaks parooli ei klapi omavahel!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappixi töötamiseks on vajalik mõned väärtused muuta. Palun muutke järgmised väljad (või jätke need samaks, mis peaksid samuti töötama)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "NB: Kui Te ei kinnita vajalikke väljasid siis kasutatakse olemasolevaid seadeid."
+
+msgid "User"
+msgstr "Kasutaja"
+
+msgid "Service"
+msgstr "Teenus"
+
+msgid "Service name"
+msgstr "Teenuse nimi"
+
+msgid "Service description"
+msgstr "Teenuse kirjeldus"
+
+msgid "Connection"
+msgstr "Ühendus"
+
+msgid "Lock the host"
+msgstr "Lukusta host"
+
+msgid "Anonymous mode"
+msgstr "Anonüümne režiim"
+
+msgid "Registration allowed"
+msgstr "Registreerimine lubatud"
+
+msgid "Use a proxy"
+msgstr "Kasuta proksit"
+
+msgid "Encryption"
+msgstr "Krüpteering"
+
+msgid "HTTPS storage"
+msgstr "HTTPS hoiustus"
+
+msgid "Force HTTPS"
+msgstr "Sunni HTTPS kasutus"
+
+msgid "Compression"
+msgstr "Pakkimine"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "See lehekülg aitab Teil täpsustada hosti kuhu Jappix ennast ühendab. Te võite selle jätta nii nagu on kui soovite kasutada ametliku teenuse hosti."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Võib-olla Te ei tea mis on BOSH server? See on vahelüli Jappixi ja XMPP serveri vahel, see on vajalik tehniliste piirangute tõttu."
+
+msgid "Main host"
+msgstr "Põhiline host"
+
+msgid "Groupchat host"
+msgstr "Grupivestluse host"
+
+msgid "Anonymous host"
+msgstr "Anonüümne host"
+
+msgid "Directory host"
+msgstr "Kataloogi host"
+
+msgid "BOSH host"
+msgstr "BOSH host"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Te saate paigaldada lisatarkvara oma serverile, et laiendada Jappixi võimalusi."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Et seda tegevust sooritada, peate Te olema serverisse sisse logitud administraatorina."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Kui te olete seadistamise lõpetanud, tekitab Jappix vahemälu failid. See võib aega võtta nii, et oodake millal rakendus on nähtaval ning ärge vajutage ühtegi nuppu."
+
+msgid "Thanks for using Jappix!"
+msgstr "Aitäh, et kasutate Jappixit!"
+
+msgid "Next"
+msgstr "Järgmine"
+
+msgid "Finish"
+msgstr "Valmis"
+
+msgid "Check again"
+msgstr "Kontrolli uuesti"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Kataloogil ei ole kirjutusõigusi, lisage need õigused sellele asukohale %s."
+
+msgid "%s is installed on your system."
+msgstr "%s on Teie süsteemi paigaldatud."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s ei ole Teie süsteemi paigaldatud, Te peaksite paigaldama %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP maksimaalse faili üleslaadimise mahu piirang on piisav (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP maksimaalse faili üleslaadimise mahu piirang ei ole piisav (%1s), Te peaksite selle %2s määrama %3s."
+
+msgid "Jappix manager"
+msgstr "Jappixi haldur"
+
+msgid "Manager access"
+msgstr "Halduri juurdepääs"
+
+msgid "Statistics"
+msgstr "Statistika"
+
+msgid "Hosts"
+msgstr "Hostid"
+
+msgid "Design"
+msgstr "Disain"
+
+msgid "Repeat"
+msgstr "Korda"
+
+msgid "All"
+msgstr "Kõik"
+
+msgid "Horizontal"
+msgstr "Horisontaalne"
+
+msgid "Vertical"
+msgstr "Vertikaalne"
+
+msgid "Center"
+msgstr "Keskel"
+
+msgid "Left"
+msgstr "Vasakule"
+
+msgid "Right"
+msgstr "Paremale"
+
+msgid "Top"
+msgstr "Üles"
+
+msgid "Bottom"
+msgstr "Alla"
+
+msgid "Adapt"
+msgstr "Kohanda"
+
+msgid "Color"
+msgstr "Värv"
+
+msgid "Users"
+msgstr "Kasutajad"
+
+msgid "Updates"
+msgstr "Uuendused"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "See on keelatud ala: ainult autoriseeritud kasutajad saavad siia juurdepääsu."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Palun täitke alljärgnev vorm, et administraatori paneelile juurdepääs saada."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Et turvalisust suurendada, siis sessioonid on ajalise piiranguga ja kui brauser sulgeda siis Teid logitakse välja."
+
+msgid "Credentials"
+msgstr "Isikutunnistus"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Teid on välja logitud. Nägemiseni!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Teid ei olnud võimalik kinnitada kui administraatorit. Kontrollige sisestatud andmeid!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Põhiline statistika on protsessitud Jappixi poolt, Te leiate selle siit alt."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Muutke oma Jappixi konfiguratsiooni selle tööriista abil."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Muutke XMPP hosti, mida Jappix pakub, selle tööriista abil."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Kõiki Jappixi poolt salvestatud faile saab hallata selle tööriista abil: palun valige alamkataloog ja hakake selle sisu muutma!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix on täielikult kohandatav: Te saate selle kujundust muuta siin."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "See ei ole õige pildi formaat, palun kasutage PNG, GIF või JPG formaati!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Pilti ei olnud võimalik vastu võtta, kas soovite uuesti proovida?"
+
+msgid "Your image was added to the list!"
+msgstr "Teie pilt lisati nimekirja!"
+
+msgid "Changes saved!"
+msgstr "Muudatused salvestatud!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Te saate lisada rohkem kui ühe administraatori. Selle tööriistaga saate ka parooli muuta."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Selle tööriistaga saate Jappixit uuendada või vaadata kas uus versioon on saadaval. Informatsioon uue versiooni kohta on inglise keeles."
+
+msgid "Access statistics"
+msgstr "Juurdepääs statistikale"
+
+msgid "Share statistics"
+msgstr "Jaga statistikat"
+
+msgid "Other statistics"
+msgstr "Muu statistika"
+
+msgid "January"
+msgstr "Jaanuar"
+
+msgid "February"
+msgstr "Veebruar"
+
+msgid "March"
+msgstr "Märts"
+
+msgid "April"
+msgstr "Aprill"
+
+msgid "May"
+msgstr "Mai"
+
+msgid "June"
+msgstr "Juuni"
+
+msgid "July"
+msgstr "Juuli"
+
+msgid "August"
+msgstr "August"
+
+msgid "September"
+msgstr "September"
+
+msgid "October"
+msgstr "Oktoober"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "Detsember"
+
+msgid "Monday"
+msgstr "Esmaspäev"
+
+msgid "Tuesday"
+msgstr "Teisipäev"
+
+msgid "Wednesday"
+msgstr "Kolmapäev"
+
+msgid "Thursday"
+msgstr "Neljapäev"
+
+msgid "Friday"
+msgstr "Reede"
+
+msgid "Saturday"
+msgstr "Laupäev"
+
+msgid "Sunday"
+msgstr "Pühapäev"
+
+msgid "Total"
+msgstr "Kokku"
+
+msgid "Cache"
+msgstr "Vahemälu"
+
+msgid "Logs"
+msgstr "Logid"
+
+msgid "Music"
+msgstr "Muusika"
+
+msgid "Backgrounds"
+msgstr "Tagataustad"
+
+msgid "Share"
+msgstr "Jaga"
+
+msgid "Background"
+msgstr "Tagataust"
+
+msgid "Notice"
+msgstr "Teade"
+
+msgid "Your design preferences have been saved!"
+msgstr "Teie kujunduse seadistused on salvestatud!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Palun kontrollige väljasid: midagi on puudu!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Selle tööriistaga saate muuta Jappixi tagatausta. Te saate panna kas ühte värvi tagatausta või üles laadida pildi. Laske kujutlusvõimel lennata!"
+
+msgid "Use default background"
+msgstr "Kasutage olemasolevat tagatausta"
+
+msgid "Use your own image"
+msgstr "Kasutage enda üles laetud pilti"
+
+msgid "Select a background to use and change the display options."
+msgstr "Valige tagaataust ja seejärel valige kuidas seda kuvama peaks."
+
+msgid "Use your own color"
+msgstr "Kasutage enda valitud värvi"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Kirjutage HEX väärtusega värvi valik mida Te soovite tagataustaks kasutada."
+
+msgid "Manage backgrounds"
+msgstr "Tagataustade haldamine"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Selle tööriistaga saate Te lisada uusi tagatausta pilte."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Kui Te soovite mingisuguseid taustapilte eemaldada siis kasutage all olevat brauserit."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Defineerige avalehe märguanne oma teenuse kasutajatele. Nagu näiteks hoiatus sõnumid, märguanded või reklaam."
+
+msgid "Simple notice"
+msgstr "Lihtne märguanne"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Sellele märguandele saab kirjutada tavalist teksti, kood ei ole lubatud!"
+
+msgid "Advanced notice"
+msgstr "Ülendatud märguanne"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Te saate lisada märguande kus võite kasutada HTML'i, CSS'i ja JavaScripti, aga Te peate kodeerima stiili."
+
+msgid "Available updates"
+msgstr "Saadaval olevad uuendused"
+
+msgid "What's new?"
+msgstr "Mis on uut?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Teie failihoidla kataloogil ei ole kirjutusõigusi, palun lisage need!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s võib põhjustada proksi probleeme, palun suurendage väärtust %2s kuni %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Te kasutate Jappixi arendusversiooni. Uuendage seda läbi repository (hoidla) käivitades %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Uus Jappixi versioon on saadaval! Vaadake mis on uut ja käivitage uuendus!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Teil on vana Jappixi versioon. Uuendage see versioonini %s siia klikkides!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Teil näib olevat Jappixi uusim versioon, aga te saate ka manuaalselt uuendusi kontrollida siia klikkides."
+
+msgid "Check for updates"
+msgstr "Kontrolli uuendusi"
+
+msgid "Update in progress"
+msgstr "Uuendamine käigus"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix on uuendatud: Teil on nüüd kõige uuem versioon."
+
+msgid "The update has failed! Please try again later."
+msgstr "Uuendamine ebaõnnestus! Palun proovige hiljem uuesti."
+
+msgid "Downloading package..."
+msgstr "Pakkide alla laadimine..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Eemaldan hetkelisi Jappixi süsteemi faile..."
+
+msgid "Extracting package..."
+msgstr "Pakin pakke lahti..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Taastan hoiukataloogi..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix on nüüd uuendatud!"
+
+msgid "Aborted: socket error!"
+msgstr "Katkestatud: pesa viga!"
+
+msgid "Aborted: buffer error!"
+msgstr "Katkestatud: puhvri viga!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Katkestatud: kõikidel vajalikel asjadel ei ole kirjutusõigusi!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Katkestatud: ei saanud pakke lahti pakkida!"
+
+msgid "Visits"
+msgstr "Külastused"
+
+msgid "Daily"
+msgstr "Päevane"
+
+msgid "Weekly"
+msgstr "Nädalane"
+
+msgid "Monthly"
+msgstr "Kuine"
+
+msgid "Yearly"
+msgstr "Aastane"
+
+msgid "Size"
+msgstr "Suurus"
+
+msgid "Clean everything"
+msgstr "Puhasta kõik"
+
+msgid "Purge cache"
+msgstr "Puhasta vahemälu"
+
+msgid "Purge logs"
+msgstr "Puhasta logid"
+
+msgid "Purge updates"
+msgstr "Puhasta uuendused"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Failihoidla mida Te puhastasite on nüüd tühi!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Hoidke oma Jappix värske ja kiire, puhastage failihoidlaid regulaarselt!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Lae üles oma muusikat (OGG Vorbis, MP3 või WAV) et seda saaks Jappix'is kuulata!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Fail mida Te tahtsite üles laadida peab olema väiksem kui %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Selle tööriistaga saate ennast kursis hoida mida Teie kasutajad serveris hoiavad ja vajaduse korral eemaldada ebasobivaid materjale."
+
+msgid "Title"
+msgstr "Pealkiri"
+
+msgid "Artist"
+msgstr "Esitaja"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Fail"
+
+msgid "Upload"
+msgstr "Üleslaadimine"
+
+msgid "The folder is empty."
+msgstr "Kaust on tühi."
+
+msgid "The music could not be received, please retry!"
+msgstr "Muusikat ei saadud vastu võtta, proovige uuesti!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Vale muusikafaili formaat, palun laadige üles OGG Vorbis, MP3 või WAV formaadis!"
+
+msgid "Your music has been added!"
+msgstr "Teie muusika on lisatud!"
+
+msgid "The selected elements have been removed."
+msgstr "Valitud elemendid on eemaldatud."
+
+msgid "You must select elements to remove!"
+msgstr "Te peate valima elemente mida eemaldada!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Selle tööriistaga saate lisada uue kasutaja või muuta parooli. Palun lisage tugev parool!"
+
+msgid "Manage"
+msgstr "Halda"
+
+msgid "List"
+msgstr "Nimekiri"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Selle tööriistaga saate eemaldada kasutajaid. Viimast kasutajat eemaldada ei saa, vähemalt üks peab alati alles jääma."
+
+msgid "The user has been added!"
+msgstr "Kasutaja on lisatud!"
+
+msgid "The chosen users have been removed."
+msgstr "Valitud kasutajad on eemaldatud."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Te peate valima ühe või mitu kasutajat keda eemaldada!"
+
+msgid "Yesterday"
+msgstr "Eile"
+
+msgid "%s days ago"
+msgstr "%s päeva tagasi"
+
+msgid "User currently active"
+msgstr "Hetkel aktiivsed kasutajad"
+
+msgid "Last seen: %s"
+msgstr "Viimati nähtud: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inaktiivsed alates: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Näib, et Teie sõber ei ole Teie sõnumeid kätte saanud!"
+
+msgid "Static content server"
+msgstr "Staatilise sisuga server"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Siin on staatilise sisuga serverid %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Soovitatud sõbrad"
+
+msgid "Check all"
+msgstr "Vali kõik"
+
+msgid "Uncheck all"
+msgstr "Eemalda valik kõigelt"
+
+msgid "Choose"
+msgstr "Vali"
+
+msgid "List name"
+msgstr "Näita nime"
+
+msgid "Allow"
+msgstr "Luba"
+
+msgid "Deny"
+msgstr "Keela"
+
+msgid "Group"
+msgstr "Grupp"
+
+msgid "Subscription"
+msgstr "Tellimus"
+
+msgid "Both"
+msgstr "Mõlemad"
+
+msgid "From"
+msgstr "Kellelt"
+
+msgid "Everybody"
+msgstr "Igaüks"
+
+msgid "Send messages"
+msgstr "Saada sõnum"
+
+msgid "Send queries"
+msgstr "Saada päringud"
+
+msgid "See my status"
+msgstr "Vaata minu staatust"
+
+msgid "Send his/her status"
+msgstr "Saada tema staatus"
+
+msgid "Everything"
+msgstr "Kõik"
+
+msgid "Item"
+msgstr "Ühik"
+
+msgid "Order"
+msgstr "Järjekord"
+
+msgid "Active for this session"
+msgstr "Selleks sessiooniks aktiivne"
+
+msgid "Always active"
+msgstr "Alati aktiivne"
+
+msgid "User directory"
+msgstr "Kasutaja kataloog"
+
+msgid "Search a friend"
+msgstr "Otsi sõpra"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Server ei toeta nõutud detaili või ei ole see saadaval, seega detaili protsessimine on katkestatud."
+
+msgid "This is a repeat from %s"
+msgstr "%s kordab seda"
+
+msgid "Loading comments..."
+msgstr "Laen kommentaare..."
+
+msgid "Type your comment here..."
+msgstr "Kirjuta oma kommentaar siia..."
+
+msgid "Could not get the comments!"
+msgstr "Ei saanud kommentaare kätte!"
+
+msgid "Show comments"
+msgstr "Näita kommentaare"
+
+msgid "Send him/her a message"
+msgstr "Saada temale sõnum"
+
+msgid "Start a chat with him/her"
+msgstr "Alusta temaga vestlust"
+
+msgid "Media integration"
+msgstr "Meedia integratsioon"
+
+msgid "Comments locked!"
+msgstr "Kommentaarid lukus!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Kirjuta midagi mida sa tahad oma sõpradega jagada..."
+
+msgid "changed his/her nickname to %s"
+msgstr "muutis oma hüüdnime %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "kommenteeris asja üle mida sa jälgid: “%s”."
+
+msgid "Hide"
+msgstr "Peida"
+
+msgid "liked your post: “%s”."
+msgstr "linkis sinu postituse: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "tsiteeris sind kuskil: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "kirjutas sinu seinale: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "sildistas sind fotol (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "sildistas sind videol (%s)."
+
+msgid "Show"
+msgstr "Näita"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Vajad abi? Parem oleks kui sa loed meie dokumentatsiooni lehte enne kui sa selle vormi täidad!"
+
+msgid "Pubsub host"
+msgstr "Pubsub host"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix on suurepärane sotsiaalvõrgustik millele Te saate ligi pääseda kusiganes Te olete, millal iganes Te soovite ja suhelda kellega iganes Te soovite."
+
+msgid "Manager link"
+msgstr "Halduri link"
+
+msgid "User uploads server"
+msgstr "Kasutajate üleslaadimised serverisse"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Siin on kasutajate üleslaadimised %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Te saate lisada enda teenuse logo ja asendada olemasoleva. Hoolitsege selle eest, et suurus ja värvid oleksid õiged!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Lae üles iga logo soovitatud pikseli suurusega."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "See ei ole õige pildi formaat, palun valige PNG formaat!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Teie teenuse logo on edukalt muudetud!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Teie logo formaat peab olema PNG. Kui te jätate välja tühjaks siis logo ei muutu."
+
+msgid "Remove this logo"
+msgstr "Eemalda see logo"
+
+msgid "View this logo"
+msgstr "Vaata seda logo"
+
+msgid "Send a file"
+msgstr "Saada fail"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Kui te olete faili üles laadinud siis Teie sõber saab märguande Teie saadetud faili kohta."
+
+msgid "Groupchats to join"
+msgstr "Grupivestlused millega liituda"
+
+msgid "Purge sent files"
+msgstr "Puhasta saadetud failid"
+
+msgid "would like to send you a file: “%s”."
+msgstr "soovib Teile saata faili: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "on nõustunud Teie saadetud faili vastu võtma: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "on keeldunud Teie saadetud faili vastu võtmast: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "ei saanud Teie faili kätte: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "On failivahetuse pakkumise vastu võtnud: “%s”."
+
+msgid "Available shortcuts:"
+msgstr "Saadaolevad otseteed:"
+
+msgid "%s removes the chat logs"
+msgstr "%s eemaldab vestluse logid"
+
+msgid "%s joins a groupchat"
+msgstr "%s liitub grupivestlusega"
+
+msgid "%s closes the chat"
+msgstr "%s sulgeb vestluse"
+
+msgid "%s shows the user profile"
+msgstr "%s näitab kasutaja profiili"
+
+msgid "%s sends a message to the room"
+msgstr "%s saadab ruumi sõnumi"
+
+msgid "%s changes your nickname"
+msgstr "%s muudab Teie hüüdnime"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s saadab kellegile ruumis olevale sõnumi"
+
+msgid "%s changes the room topic"
+msgstr "%s muudab ruumi teema"
+
+msgid "%s kicks an user of the room"
+msgstr "%s lööb kasutaja ruumist välja"
+
+msgid "%s bans an user of the room"
+msgstr "%s paneb kasutajale ruumi keelu"
+
+msgid "%s invites someone to join the room"
+msgstr "%s kutsub kellegi ruumiga liituma"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/fa/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/fa/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..4ed874a
Binary files /dev/null and b/jappixmini/jappix/lang/fa/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/fa/LC_MESSAGES/main.po b/jappixmini/jappix/lang/fa/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..b677102
--- /dev/null
@@ -0,0 +1,1870 @@
+# Persian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "نمی‌توان جاوااسکریپت را در مرورگر شما یافت. بنابراین شما نمی‌توانید Jappix را ببینید! لطفاً این را اصلاح کنید."
+
+msgid "An open social network"
+msgstr "یک شما اجتماعی باز"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix توسط یک اشکال شبکه متوقف شده‌است. یک اشکال یا ورود بد (بررسی کنید که اعتبارات درست را وارد کرده‌اید). شرمنده بابات دردسر ایجاد شده."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "فهرست عناصر این سرور نمی‌تواند گرفته شود!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "گذرواژهٔ شما تغییر کرده‌است. شما می‌توانید با داده‌ها جدید ورودی متصل شوید."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "حساب XMPP شما حذف شده‌است. بدرود!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "شما از حساب XMPP خود خارج شده‌اید. روز خوش!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "اتاقی که شما به آن وصل شده‌اید به نظر وجود ندارد. شما می‌توانید ایجادش کنید!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "چپ گروهی خذف شد. الآن هر کس دیگری می‌تواند آن را ایجاد کند."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr ""
+
+msgid "Please enter the group chat address to join."
+msgstr ""
+
+msgid "Please enter your nickname to join %s."
+msgstr ""
+
+msgid "This room (%s) is protected with a password."
+msgstr ""
+
+msgid "Your browser is out of date!"
+msgstr "مرورگر شما منسوخ است!"
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr "وارد شدن"
+
+msgid "Register"
+msgstr "ثبت نام"
+
+msgid "Here we go!"
+msgstr "اینجا می‌رویم!"
+
+msgid "Server"
+msgstr "سرور"
+
+msgid "Password"
+msgstr "پسورد"
+
+msgid "Remember me"
+msgstr "مرا به خاطر بسپار"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "این سرویس غیر فعال شده و دسترسی شما به ان ممکن نیست"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "به دلیل مشکل شبکه‌ای، شما قطع شده‌اید. الآن چه می‌خواهید بکنید؟"
+
+msgid "Reconnect"
+msgstr "اتصال مجدد"
+
+msgid "Messages"
+msgstr "پیغام‌ها"
+
+msgid "Profile"
+msgstr "پروفایل"
+
+msgid "Options"
+msgstr "گزینه‌ها"
+
+msgid "Disconnect"
+msgstr "قطع"
+
+msgid "Filter"
+msgstr "پالایه"
+
+msgid "Add a friend"
+msgstr "افزودن یک دوست"
+
+msgid "Your groupchats"
+msgstr "گروه‌های چت شما"
+
+msgid "Manage your favorite groupchats"
+msgstr "گفتگوی گروهی محبوبتان را مدیریت کنید"
+
+msgid "More stuff"
+msgstr "چیزهای بیشتر"
+
+msgid "Show all friends"
+msgstr "مشاهده همه دوستان"
+
+msgid "Only show connected friends"
+msgstr "مشاهده دوستان انلاین"
+
+msgid "Message archives"
+msgstr "بایگانی‌های پیغام"
+
+msgid "Date"
+msgstr "تاریخ"
+
+msgid "Please select a friend to view the chat history."
+msgstr ""
+
+msgid "Nothing found for: %s"
+msgstr "چیزی یافت نشد برای: %s"
+
+msgid "A short message?"
+msgstr "یک پیغام کوتاه؟"
+
+msgid "How are you?"
+msgstr "چطورید؟"
+
+msgid "What are you doing?"
+msgstr "چکاری می‌کنید؟"
+
+msgid "Join a chat"
+msgstr "ورود به گفتگو"
+
+msgid "Status"
+msgstr "وضعیت"
+
+msgid "Available"
+msgstr "حاضر"
+
+msgid "Talkative"
+msgstr "پرحرف"
+
+msgid "Away"
+msgstr "دور"
+
+msgid "Not available"
+msgstr "ناحاضر"
+
+msgid "Busy"
+msgstr "مشغول"
+
+msgid "Mood"
+msgstr "حالت"
+
+msgid "None"
+msgstr "هیچ"
+
+msgid "Crazy"
+msgstr "دیوانه"
+
+msgid "Excited"
+msgstr "هیحان زده"
+
+msgid "Playful"
+msgstr "اهل بازی"
+
+msgid "Happy"
+msgstr "خوشحال"
+
+msgid "Shocked"
+msgstr "پاسخ همراه با اعلان"
+
+msgid "Hot"
+msgstr "داغ"
+
+msgid "Sad"
+msgstr "غمگین"
+
+msgid "Amorous"
+msgstr "عاشق"
+
+msgid "Confident"
+msgstr "اعتماد به نقس"
+
+msgid "Activity"
+msgstr "فعالیت"
+
+msgid "Chores"
+msgstr ""
+
+msgid "Drinking"
+msgstr "نوشیدن"
+
+msgid "Eating"
+msgstr "خوردن"
+
+msgid "Exercising"
+msgstr "تمرین‌کردن"
+
+msgid "Grooming"
+msgstr "آراسته‌کردن"
+
+msgid "Appointment"
+msgstr "انتصاب"
+
+msgid "Inactive"
+msgstr "غیرفعال"
+
+msgid "Relaxing"
+msgstr "آرامش"
+
+msgid "Talking"
+msgstr "گفتگو"
+
+msgid "Traveling"
+msgstr "سفر کردن"
+
+msgid "Working"
+msgstr "کار کردن"
+
+msgid "View profile"
+msgstr "نمایش مشخصات"
+
+msgid "Repeat this notice"
+msgstr "تکرار این موضوع"
+
+msgid "Remove this notice"
+msgstr "حذف این موضوع"
+
+msgid "Your profile"
+msgstr "مشخصات شما"
+
+msgid "Identity"
+msgstr "هویت"
+
+msgid "Profile image"
+msgstr "مشخصات شما"
+
+msgid "Others"
+msgstr "دیگران"
+
+msgid "Personal"
+msgstr "شخصی"
+
+msgid "Complete name"
+msgstr "نام کامل"
+
+msgid "Nickname"
+msgstr "نام کاربری"
+
+msgid "First name"
+msgstr "نام"
+
+msgid "Last name"
+msgstr "نام خانوادگی"
+
+msgid "Date of birth"
+msgstr "تاریخ تولد"
+
+msgid "Contact"
+msgstr "مشخصات تماس"
+
+msgid "E-mail"
+msgstr "ایمیل"
+
+msgid "Phone"
+msgstr "تلفن"
+
+msgid "Website"
+msgstr "آدرس وب سایت"
+
+msgid "Current"
+msgstr "واحد پول"
+
+msgid "Delete"
+msgstr "حذف‌کردن"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "چه متأسر کننده! شما تصویر پروفایلی در کارت شناساییتان تعیین نکرده‌اید!"
+
+msgid "Address"
+msgstr "نشانی"
+
+msgid "Street"
+msgstr "خیابان"
+
+msgid "City"
+msgstr "شهر"
+
+msgid "Postal code"
+msgstr "کد پستی"
+
+msgid "Country"
+msgstr "کشور"
+
+msgid "Biography"
+msgstr "زندگی‌نامه"
+
+msgid "Important notice"
+msgstr "اخطار مهم"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr ""
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr ""
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "ذخیره"
+
+msgid "Cancel"
+msgstr "انصراف"
+
+msgid "Edit options"
+msgstr "ویرایش اختیارات"
+
+msgid "Channel"
+msgstr "کانال"
+
+msgid "Commands"
+msgstr "دستورات"
+
+msgid "Sounds"
+msgstr "صداها"
+
+msgid "Privacy"
+msgstr "حریم خصوصی"
+
+msgid "Message archiving"
+msgstr "بایگانی پیام"
+
+msgid "Store a history of your chats"
+msgstr "ذخیرهٔ تاریخچهٔ گفتگوهای شما"
+
+msgid "Geolocation"
+msgstr "منطقهٔ جغرافیایی"
+
+msgid "Empty"
+msgstr "خالی"
+
+msgid "Empty channel"
+msgstr "کانال خالی"
+
+msgid "Persistent"
+msgstr "ماندگار"
+
+msgid "Maximum notices"
+msgstr "بیشترین آگاهی‌دادن‌ها"
+
+msgid "Account"
+msgstr "حساب"
+
+msgid "Change password"
+msgstr "تغییر گذرواژه"
+
+msgid "Delete account"
+msgstr "حذف حساب"
+
+msgid "Old"
+msgstr "قدیمی"
+
+msgid "New (2 times)"
+msgstr "جدید (۲ مرتبه)"
+
+msgid "Continue"
+msgstr "ادامه"
+
+msgid "To"
+msgstr "به"
+
+msgid "Close"
+msgstr "بستن"
+
+msgid "unknown"
+msgstr "ناشناخته"
+
+msgid "Unavailable"
+msgstr "ناموجود"
+
+msgid "is now"
+msgstr "الآن هست"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "لظفاً صبر کنید تا آواتار شما بارگذاری شود..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "اینجاست! یک تصویر زیبا و جدید پروفایل!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr ""
+
+msgid "Reply"
+msgstr "پاسخ"
+
+msgid "Error"
+msgstr "خطا"
+
+msgid "Click here to solve the error"
+msgstr "اینجا را برای حل ایراد کلیک کنید"
+
+msgid "You"
+msgstr "شما"
+
+msgid "Remove"
+msgstr "حذف"
+
+msgid "Rename"
+msgstr "تغییر نام"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr ""
+
+msgid "Smiley insertion"
+msgstr "افزودن شکلک"
+
+msgid "Change style"
+msgstr "تغییر سبک"
+
+msgid "Text in bold"
+msgstr "متن ضخیم"
+
+msgid "Text in italic"
+msgstr "متن مورب"
+
+msgid "Underlined text"
+msgstr "متن زیرخط کشیده شده"
+
+msgid "Save chat"
+msgstr "ذخیرهٔ گفتگو"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr ""
+
+msgid "This chat is empty!"
+msgstr "این گفتگو خالی‌است!"
+
+msgid "Generate file!"
+msgstr "ساختن پرونده!"
+
+msgid "Download file!"
+msgstr "بارگیری پرونده!"
+
+msgid "Clean current chat"
+msgstr "پاکسازی گفتگوی فعلی"
+
+msgid "View chat history"
+msgstr "دیدن تاریخچهٔ گفتگو"
+
+msgid "Show user profile"
+msgstr "نمایش پروفایل کاربری"
+
+msgid "Add this contact to your friends"
+msgstr "افزودن این تماس به دوستان شما"
+
+msgid "Add this groupchat to your favorites"
+msgstr "افزودن این گفتگوی گروهی به محبوب‌ها شما"
+
+msgid "All tabs"
+msgstr "همهٔ برگه‌ها"
+
+msgid "Close this tab"
+msgstr "بستن این برگه"
+
+msgid "no subject defined for this room."
+msgstr "موضوعی برای این اتاق تعیین نشده‌است."
+
+msgid "Administration panel for this room"
+msgstr "پنل مدیریتی این اتاق"
+
+msgid "Moderators"
+msgstr "مدیران"
+
+msgid "Participants"
+msgstr "شریک‌ها"
+
+msgid "Visitors"
+msgstr "بازدیدکنندگان"
+
+msgid "Manage favorite rooms"
+msgstr "مدیریت اتاق‌ها محبوب شده"
+
+msgid "Change favorites"
+msgstr "عوض‌کردن محبوب شده‌ها"
+
+msgid "Search a room"
+msgstr "جستجوی یک اتاق"
+
+msgid "Select a favorite"
+msgstr "انتخاب یکی از محبوب شده‌ها"
+
+msgid "Getting the name..."
+msgstr "گرفتن نام..."
+
+msgid "Gateway"
+msgstr "دروازه"
+
+msgid "Name"
+msgstr "نام"
+
+msgid "Room"
+msgstr "اتاق"
+
+msgid "Add"
+msgstr "افزودن"
+
+msgid "Edit"
+msgstr "ویرایش"
+
+msgid "Search a room on"
+msgstr ""
+
+msgid "No room found on this server."
+msgstr "اتاقی در این سرور یافت نشد."
+
+msgid "Service discovery"
+msgstr "جستجوی "
+
+msgid "Server to query"
+msgstr "کارساز برای پرس‌وجو"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "شرمنده. ولی موجودیت هیچ نتیجه‌ای را برنگرداند!"
+
+msgid "Accounts"
+msgstr "حساب‌ها"
+
+msgid "Authentications"
+msgstr "تصدیقات"
+
+msgid "Automation"
+msgstr "خودکاری"
+
+msgid "Clients"
+msgstr "مشتری‌ها"
+
+msgid "Collaboration"
+msgstr "همکاری"
+
+msgid "Components"
+msgstr "اجزاء"
+
+msgid "Rooms"
+msgstr "اتاق‌ها"
+
+msgid "Directories"
+msgstr ""
+
+msgid "Gateways"
+msgstr "دروازه‌ها"
+
+msgid "News"
+msgstr "اخبار"
+
+msgid "Hierarchy"
+msgstr "سلسه مراتبی"
+
+msgid "Proxies"
+msgstr "پروکسی‌ها"
+
+msgid "Publication/Subscription"
+msgstr ""
+
+msgid "Storage"
+msgstr "انباره"
+
+msgid "Service offline or broken"
+msgstr ""
+
+msgid "Your inbox"
+msgstr "صندوق ورودی شما"
+
+msgid "Available actions"
+msgstr "اقدام‌ها موجود"
+
+msgid "Clean"
+msgstr "تمیز"
+
+msgid "New"
+msgstr "جدید"
+
+msgid "Received"
+msgstr "دریافت شده"
+
+msgid "Subject"
+msgstr "موضوع"
+
+msgid "Content"
+msgstr "محتوا"
+
+msgid "Send message"
+msgstr "فرستادن پیام"
+
+msgid "Your inbox is empty."
+msgstr "صندوق ورودی شما خالی‌است."
+
+msgid "MUC administration"
+msgstr "مدیریت MUC"
+
+msgid "You administrate this room"
+msgstr ""
+
+msgid "Enter new subject"
+msgstr "افزودن عنوان جدید"
+
+msgid "Configuration"
+msgstr "پیکربندی"
+
+msgid "Authorizations"
+msgstr "اجازه‌ها"
+
+msgid "Member list"
+msgstr "فهرست عضو"
+
+msgid "Owner list"
+msgstr "فهرست دارنده"
+
+msgid "Administrator list"
+msgstr "فهرست مدیران"
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr "افزودن یک وررو"
+
+msgid "Destroy this MUC"
+msgstr "نابودسازی این MUC"
+
+msgid "Yes, let's do it!"
+msgstr "بله. بگذار انجامش دهیم!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "دوست شما به مکالمه توجه می‌کنند."
+
+msgid "Your friend is writing a message..."
+msgstr "دوست شما در حال نوشتن یک پیام است..."
+
+msgid "Your friend stopped writing a message."
+msgstr "دوست شما از نوشتن پیامی باز ایستاد."
+
+msgid "Your friend is doing something else."
+msgstr "دوست شما کا دیگری می‌کند."
+
+msgid "Your friend closed the chat."
+msgstr "دوست شما گفتگو را بست."
+
+msgid "Requesting this service..."
+msgstr "درخواست کردن این سرویس..."
+
+msgid "Loading"
+msgstr "بارگیری"
+
+msgid "joined the chat room"
+msgstr "به اتاق گفتگو پیوست"
+
+msgid "left the chat room"
+msgstr "ترک‌کردن اتاق گفتگو"
+
+msgid "no status"
+msgstr "بی‌وضعیت"
+
+msgid "has been kicked"
+msgstr "بیرون شده‌است"
+
+msgid "has been banned"
+msgstr "بسته شده‌است"
+
+msgid "no reason"
+msgstr "بی‌دلیل"
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr "سلام!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "خوش‌آمدید به %1s. «%2s»"
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr "قبلی"
+
+msgid "General"
+msgstr "عمومی"
+
+msgid "Advanced"
+msgstr "پیشرفته"
+
+msgid "Resource"
+msgstr "منبع"
+
+msgid "Priority"
+msgstr "اولویت"
+
+msgid "Low"
+msgstr "کم"
+
+msgid "Medium"
+msgstr "متوسط"
+
+msgid "High"
+msgstr "زیاد"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr "صفحهٔ واردشدن"
+
+msgid "Share this link with your friends:"
+msgstr "اشتراک این پیوند با دوستانتان:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr "مورد نیاز"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr ""
+
+msgid "Manager"
+msgstr "مدیر"
+
+msgid "Project"
+msgstr "پروژه"
+
+msgid "Encrypted"
+msgstr "رمزنگاری‌شده"
+
+msgid "Unencrypted"
+msgstr "رمزنگاری‌نشده"
+
+msgid "Where are you?"
+msgstr ""
+
+msgid "What's up with you?"
+msgstr ""
+
+msgid "Fetching the social channel..."
+msgstr ""
+
+msgid "You are synchronized with your network."
+msgstr ""
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr ""
+
+msgid "Media viewer"
+msgstr "نمایشگر رسانه"
+
+msgid "Browse"
+msgstr "جستجو"
+
+msgid "Command"
+msgstr "دستور"
+
+msgid "Subscribe"
+msgstr "تصویب‌کردن"
+
+msgid "Join"
+msgstr "وصل‌شدن"
+
+msgid "Automatic"
+msgstr "خودکار"
+
+msgid "Search"
+msgstr "جستجو"
+
+msgid "No result!"
+msgstr "بی‌نتیجه!"
+
+msgid "No notifications."
+msgstr ""
+
+msgid "would like to add you as a friend."
+msgstr "دوست دارد شما را به عنوان یک بیافزاید."
+
+msgid "would like you to join this chatroom:"
+msgstr ""
+
+msgid "Do you accept?"
+msgstr "قبول می‌کنید؟"
+
+msgid "Yes"
+msgstr "بله"
+
+msgid "No"
+msgstr "خیر"
+
+msgid "would like to get authorization."
+msgstr "دوست دارد که دسترسی بگیرد."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr "ارائه‌کردن"
+
+msgid "Client"
+msgstr "مشتری"
+
+msgid "System"
+msgstr "سامانه"
+
+msgid "Local time"
+msgstr "زمان محلی"
+
+msgid "Comments"
+msgstr "توضیحات"
+
+msgid "User profile"
+msgstr "پروفایل کاربری"
+
+msgid "See his/her position on the globe"
+msgstr ""
+
+msgid "Confirm"
+msgstr "تأیید"
+
+msgid "anonymous mode"
+msgstr "حالت ناشناس"
+
+msgid "Groups"
+msgstr "گروه‌ها"
+
+msgid "Unclassified"
+msgstr "طبقه‌بندی‌نشده"
+
+msgid "Authorize"
+msgstr "اجازه‌دادن"
+
+msgid "Ask for authorization"
+msgstr "درخواست برای اجازه‌دادن"
+
+msgid "Unblock"
+msgstr "بازکردن"
+
+msgid "Prohibit"
+msgstr "منع‌کردن"
+
+msgid "Block"
+msgstr "بستن"
+
+msgid "Chat"
+msgstr "گفتگو"
+
+msgid "Groupchat"
+msgstr "گروه گفتگو"
+
+msgid "Jappix Mobile"
+msgstr "Jappix همراه"
+
+msgid "Desktop"
+msgstr "میزکار"
+
+msgid "Mobile"
+msgstr "گوشی همراه"
+
+msgid "Please wait..."
+msgstr "لطفاً صبرکنید..."
+
+msgid "Please enable JavaScript"
+msgstr "لطفاً جاوااسکریپت را فعال کنید"
+
+msgid "Your channel"
+msgstr "کانال شما"
+
+msgid "Channel of"
+msgstr "کانال"
+
+msgid "More notices..."
+msgstr "پیغام‌های بیشتر..."
+
+msgid "Attach a file"
+msgstr "متصل‌کردن یک پرونده"
+
+msgid "Send"
+msgstr "ارسال"
+
+msgid "Unattach the file"
+msgstr "جداکردن پرونده"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr "شکست در اجازه‌گیری"
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr "خدمت ناموجود است"
+
+msgid "Internal server error, try later"
+msgstr "ایراد داخلی کارساز. بعداً تلاش کنید"
+
+msgid "Your form has been sent."
+msgstr "فرم شما فرستاده شده‌است."
+
+msgid "Application"
+msgstr "برنامه"
+
+msgid "XMPP links"
+msgstr "پیوند XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr ""
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr ""
+
+msgid "Friends"
+msgstr ""
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr "دوستان آفلاین"
+
+msgid "Don't hide offline friends"
+msgstr "دوستان آفلاین را مخفی نکن"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr "نام ناشناخته"
+
+msgid "Unknown country"
+msgstr "کشور ناشناخته"
+
+msgid "Click to enable"
+msgstr "کلیک برای فعال‌سازی"
+
+msgid "Click to disable"
+msgstr "کلیک برای غیرفعال‌سازی"
+
+msgid "Installation"
+msgstr "نصب"
+
+msgid "Jappix installation"
+msgstr "نصب Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "به نصب Jappix خوش‌آمدید!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr "خوش‌آمدید"
+
+msgid "Storage configuration"
+msgstr "تنظیمات حافظه"
+
+msgid "Administrator account"
+msgstr "حساب مدیر"
+
+msgid "Main configuration"
+msgstr "تنظیمات اصلی"
+
+msgid "Hosts configuration"
+msgstr "تنظیمات میزبان"
+
+msgid "Services installation"
+msgstr "نصب خدمات"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr "پوشه قابل ویرایش است. می‌توانید ادامه دهید!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr "کاربر"
+
+msgid "Service"
+msgstr "خدمت"
+
+msgid "Service name"
+msgstr "نام خدمت"
+
+msgid "Service description"
+msgstr "توضیح خدمت"
+
+msgid "Connection"
+msgstr "اتصال"
+
+msgid "Lock the host"
+msgstr "قفل‌کردن میزبان"
+
+msgid "Anonymous mode"
+msgstr "حالت ناشناس"
+
+msgid "Registration allowed"
+msgstr "ثبت‌نام اجازه‌داده شده‌است"
+
+msgid "Use a proxy"
+msgstr "استفاده از پراکسی"
+
+msgid "Encryption"
+msgstr "رمزنگاری"
+
+msgid "HTTPS storage"
+msgstr "انبارهٔ HTTPS"
+
+msgid "Force HTTPS"
+msgstr "HTTPS اجباری"
+
+msgid "Compression"
+msgstr "فشرده‌سازی"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr "میزبان اصلی"
+
+msgid "Groupchat host"
+msgstr "میزبان گفتگوی گروهی"
+
+msgid "Anonymous host"
+msgstr "میزبان ناشناس"
+
+msgid "Directory host"
+msgstr "میزبان پوشه"
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr "ممنون برای استفاده از Jappix!"
+
+msgid "Next"
+msgstr "بعدی"
+
+msgid "Finish"
+msgstr "تمام"
+
+msgid "Check again"
+msgstr "بررسی مجدد"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "حداکثر اندازهٔ بارگذاری PHP کافی است (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr "مدیریت‌کنندهٔ Jappix"
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr "آمارها"
+
+msgid "Hosts"
+msgstr "میزبان‌ها"
+
+msgid "Design"
+msgstr "طراحی"
+
+msgid "Repeat"
+msgstr "تکرار"
+
+msgid "All"
+msgstr "همه"
+
+msgid "Horizontal"
+msgstr "افقی"
+
+msgid "Vertical"
+msgstr "عمودی"
+
+msgid "Center"
+msgstr "وسط"
+
+msgid "Left"
+msgstr "چپ"
+
+msgid "Right"
+msgstr "راست"
+
+msgid "Top"
+msgstr "بالا"
+
+msgid "Bottom"
+msgstr "زیر"
+
+msgid "Adapt"
+msgstr "تطابق"
+
+msgid "Color"
+msgstr "رنگ"
+
+msgid "Users"
+msgstr "کاربران"
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr "اختیارات"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "شما خارج شده‌اید. بدرود!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr "تغییرات ذخیره شد!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr "سایر آمارها"
+
+msgid "January"
+msgstr "ژوئن"
+
+msgid "February"
+msgstr "فوریه"
+
+msgid "March"
+msgstr "مارس"
+
+msgid "April"
+msgstr "آوریل"
+
+msgid "May"
+msgstr "می"
+
+msgid "June"
+msgstr ""
+
+msgid "July"
+msgstr "جولای"
+
+msgid "August"
+msgstr "آگوست"
+
+msgid "September"
+msgstr "سپتامبر"
+
+msgid "October"
+msgstr "اوکتوبر"
+
+msgid "November"
+msgstr "نوامبر"
+
+msgid "December"
+msgstr "دسامبر"
+
+msgid "Monday"
+msgstr "دوشنبه"
+
+msgid "Tuesday"
+msgstr "سه‌شنبه"
+
+msgid "Wednesday"
+msgstr "چهارشتبع"
+
+msgid "Thursday"
+msgstr "پنج‌شنبه"
+
+msgid "Friday"
+msgstr "جمعه"
+
+msgid "Saturday"
+msgstr "شنبه"
+
+msgid "Sunday"
+msgstr "یک‌شنبه"
+
+msgid "Total"
+msgstr "همه"
+
+msgid "Cache"
+msgstr "میانگیر"
+
+msgid "Logs"
+msgstr "سیاهه‌ها"
+
+msgid "Music"
+msgstr "آهنگ"
+
+msgid "Backgrounds"
+msgstr "پشت‌زمینه‌ها"
+
+msgid "Share"
+msgstr "اشتراک"
+
+msgid "Background"
+msgstr "پشت‌زمینه"
+
+msgid "Notice"
+msgstr "آگهی"
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr "لطفاً ورودی‌های خود را بررسی کنید: چیزی گم شده!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr "استفاده از پشت‌زمینهٔ پیش‌فرض"
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr "بررسی برای به‌روزرسانی‌ها"
+
+msgid "Update in progress"
+msgstr "به‌روزرسانی در جریان است"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr "بارگیری بسته..."
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr "بازکردن بسته..."
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix الآن به روز است!"
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr "بازدیدها"
+
+msgid "Daily"
+msgstr "روزانه"
+
+msgid "Weekly"
+msgstr "هفته‌ای"
+
+msgid "Monthly"
+msgstr "ماهانه"
+
+msgid "Yearly"
+msgstr "سالانه"
+
+msgid "Size"
+msgstr "اندازه"
+
+msgid "Clean everything"
+msgstr "پاکسازی همه‌چیز"
+
+msgid "Purge cache"
+msgstr "خالی‌کردن میانگیر"
+
+msgid "Purge logs"
+msgstr "خالی‌کردن سیاهه‌ها"
+
+msgid "Purge updates"
+msgstr "خالی‌کردن به‌روزرسانی‌ها"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr "عنوان"
+
+msgid "Artist"
+msgstr "عنوان"
+
+msgid "Album"
+msgstr "آلبوم"
+
+msgid "File"
+msgstr "پرونده"
+
+msgid "Upload"
+msgstr "بارگذاری"
+
+msgid "The folder is empty."
+msgstr "پوشه خالی است."
+
+msgid "The music could not be received, please retry!"
+msgstr "آهنگ نمی‌تواند گرفته شود. لطفاً مجدداً تلاش کنید!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr "آهنگ شما اضافه شده‌است!"
+
+msgid "The selected elements have been removed."
+msgstr "عنصر انتخاب شده حذف شد."
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr "مدیریت"
+
+msgid "List"
+msgstr "فهرست"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr "کاربر اضافه شده‌است!"
+
+msgid "The chosen users have been removed."
+msgstr "کاربرهای انتخاب شده حذف شده‌اند."
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr "دیروز"
+
+msgid "%s days ago"
+msgstr "%s روز پیش"
+
+msgid "User currently active"
+msgstr "کاربر فعال در حال حاضر"
+
+msgid "Last seen: %s"
+msgstr "آخرین دیده شدن: %s"
+
+msgid "Inactive since: %s"
+msgstr "غیرفعال از: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr "کارساز محتویات ثابت"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr "دوستان پیشنهادشده"
+
+msgid "Check all"
+msgstr "انتخاب‌کردن همه"
+
+msgid "Uncheck all"
+msgstr "از انتخاب درآوردن همه"
+
+msgid "Choose"
+msgstr "انتخاب"
+
+msgid "List name"
+msgstr "فهرست نام"
+
+msgid "Allow"
+msgstr "اجازه‌دادن"
+
+msgid "Deny"
+msgstr "ردکردن"
+
+msgid "Group"
+msgstr "گروه"
+
+msgid "Subscription"
+msgstr "اشتراک"
+
+msgid "Both"
+msgstr "هردو"
+
+msgid "From"
+msgstr "از"
+
+msgid "Everybody"
+msgstr "همه"
+
+msgid "Send messages"
+msgstr "پیام‌ها را بفرست"
+
+msgid "Send queries"
+msgstr "پرس‌وجو را بفرست"
+
+msgid "See my status"
+msgstr "وضعیت من را ببین"
+
+msgid "Send his/her status"
+msgstr "وضعیتش را بفرست"
+
+msgid "Everything"
+msgstr "همه‌چیز"
+
+msgid "Item"
+msgstr "قلم"
+
+msgid "Order"
+msgstr "ترتیب"
+
+msgid "Active for this session"
+msgstr "فعال برای این نشست"
+
+msgid "Always active"
+msgstr "همیشه فعال"
+
+msgid "User directory"
+msgstr "پوشهٔ کاربری"
+
+msgid "Search a friend"
+msgstr "جستجوی یک دوست"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr "این یک تکراری از %s است."
+
+msgid "Loading comments..."
+msgstr "بارگذاری توضیحات..."
+
+msgid "Type your comment here..."
+msgstr "توضیح خود را اینجا بنویسید..."
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr "نمایش توضیحات"
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr "نام مستعارش را به %s تغییر داد"
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr "مخفی"
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr "نمایش"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr "مدیر پیوند"
+
+msgid "User uploads server"
+msgstr "کارساز بارگذاری کاربر"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/fr/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/fr/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..7716c12
Binary files /dev/null and b/jappixmini/jappix/lang/fr/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/fr/LC_MESSAGES/main.po b/jappixmini/jappix/lang/fr/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..38cf556
--- /dev/null
@@ -0,0 +1,1870 @@
+# French translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript est absent dans votre navigateur, vous ne pourrez donc pas lancer Jappix. Corrigez cela."
+
+msgid "An open social network"
+msgstr "Un réseau social libre"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix a été interrompu par un problème réseau, un bug ou de mauvais identifiants (vérifiez-les !). Nous sommes désolés pour ce souci."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "La liste des éléments présents sur ce serveur n'a pas pu être obtenue."
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Votre mot de passe a été changé, vous pouvez maintenant vous connecter à votre compte avec vos nouveaux identifiants."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Votre compte XMPP a été effacé, au revoir !"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Vous avez été déconnecté avec succès de votre compte XMPP, bonne journée !"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Le salon que vous avez rejoint semble ne pas exister. Pourquoi vous ne le créeriez pas ?"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Le salon a été supprimé avec succès, maintenant quelqu'un d'autre pourra le recréer."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "L'utilisateur que vous souhaitez joindre n'est actuellement pas présent dans le salon."
+
+msgid "Please enter the group chat address to join."
+msgstr "Veuillez entrer l'adresse du salon à rejoindre."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Veuillez entrer votre pseudonyme pour rejoindre %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Ce salon (%s) est protégé par un mot de passe."
+
+msgid "Your browser is out of date!"
+msgstr "Votre navigateur n'est pas à jour !"
+
+msgid "Last %s version is better!"
+msgstr "La dernière version de %s est mieux !"
+
+msgid "Login"
+msgstr "Connexion"
+
+msgid "Register"
+msgstr "Inscription"
+
+msgid "Here we go!"
+msgstr "Allons-y !"
+
+msgid "Server"
+msgstr "Serveur"
+
+msgid "Password"
+msgstr "Mot de passe"
+
+msgid "Remember me"
+msgstr "Se souvenir"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Cet outil a été désactivé, vous ne pouvez pas l'utiliser !"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "À cause d'un problème réseau, vous avez été déconnecté. Que voulez-vous faire à présent ? "
+
+msgid "Reconnect"
+msgstr "Reconnexion"
+
+msgid "Messages"
+msgstr "Messages"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Préférences"
+
+msgid "Disconnect"
+msgstr "Déconnexion"
+
+msgid "Filter"
+msgstr "Filtrer"
+
+msgid "Add a friend"
+msgstr "Ajouter un ami"
+
+msgid "Your groupchats"
+msgstr "Vos salons de discussion"
+
+msgid "Manage your favorite groupchats"
+msgstr "Gérer mes salons favoris"
+
+msgid "More stuff"
+msgstr "Plus de choses"
+
+msgid "Show all friends"
+msgstr "Afficher tous les amis"
+
+msgid "Only show connected friends"
+msgstr "N'afficher que les amis en ligne"
+
+msgid "Message archives"
+msgstr "Archives des messages"
+
+msgid "Date"
+msgstr "Date"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Sélectionnez un ami pour voir l'historique de discussion."
+
+msgid "Nothing found for: %s"
+msgstr "Rien de trouvé pour : %s"
+
+msgid "A short message?"
+msgstr "Un petit message ?"
+
+msgid "How are you?"
+msgstr "Comment allez-vous ?"
+
+msgid "What are you doing?"
+msgstr "Que faites-vous en ce moment ?"
+
+msgid "Join a chat"
+msgstr "Rejoindre une discussion"
+
+msgid "Status"
+msgstr "Statut"
+
+msgid "Available"
+msgstr "Disponible"
+
+msgid "Talkative"
+msgstr "Bavard(e)"
+
+msgid "Away"
+msgstr "Absent(e)"
+
+msgid "Not available"
+msgstr "Indisponible"
+
+msgid "Busy"
+msgstr "Occupé(e)"
+
+msgid "Mood"
+msgstr "Humeur"
+
+msgid "None"
+msgstr "Aucun(e)"
+
+msgid "Crazy"
+msgstr "Cinglé(e)"
+
+msgid "Excited"
+msgstr "Excité(e)"
+
+msgid "Playful"
+msgstr "Enjoué(e)"
+
+msgid "Happy"
+msgstr "Heureux(se)"
+
+msgid "Shocked"
+msgstr "Choqué(e)"
+
+msgid "Hot"
+msgstr "Bouillant(e)"
+
+msgid "Sad"
+msgstr "Triste"
+
+msgid "Amorous"
+msgstr "Amoureux(se)"
+
+msgid "Confident"
+msgstr "Confiant(e)"
+
+msgid "Activity"
+msgstr "Activité"
+
+msgid "Chores"
+msgstr "Corvées"
+
+msgid "Drinking"
+msgstr "Boit"
+
+msgid "Eating"
+msgstr "Mange"
+
+msgid "Exercising"
+msgstr "S'exerçant "
+
+msgid "Grooming"
+msgstr "Toilette"
+
+msgid "Appointment"
+msgstr "Rendez-vous"
+
+msgid "Inactive"
+msgstr "Inactif(ve)"
+
+msgid "Relaxing"
+msgstr "Se relaxe"
+
+msgid "Talking"
+msgstr "Discute"
+
+msgid "Traveling"
+msgstr "En voyage"
+
+msgid "Working"
+msgstr "Travaille"
+
+msgid "View profile"
+msgstr "Voir le profil"
+
+msgid "Repeat this notice"
+msgstr "Répéter cet avis"
+
+msgid "Remove this notice"
+msgstr "Effacer cet avis"
+
+msgid "Your profile"
+msgstr "Votre profil"
+
+msgid "Identity"
+msgstr "Identité"
+
+msgid "Profile image"
+msgstr "Photo de profil"
+
+msgid "Others"
+msgstr "Autres"
+
+msgid "Personal"
+msgstr "Personnel"
+
+msgid "Complete name"
+msgstr "Nom complet"
+
+msgid "Nickname"
+msgstr "Pseudonyme"
+
+msgid "First name"
+msgstr "Prénom"
+
+msgid "Last name"
+msgstr "Nom"
+
+msgid "Date of birth"
+msgstr "Anniversaire"
+
+msgid "Contact"
+msgstr "Coordonnées"
+
+msgid "E-mail"
+msgstr "Courriel"
+
+msgid "Phone"
+msgstr "Téléphone"
+
+msgid "Website"
+msgstr "Site web"
+
+msgid "Current"
+msgstr "Actuel"
+
+msgid "Delete"
+msgstr "Supprimer"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Comment ça ? Vous n'avez pas de photo de profil définie dans votre carte d'identité !"
+
+msgid "Address"
+msgstr "Adresse"
+
+msgid "Street"
+msgstr "Rue"
+
+msgid "City"
+msgstr "Ville"
+
+msgid "Postal code"
+msgstr "Code postal"
+
+msgid "Country"
+msgstr "Pays"
+
+msgid "Biography"
+msgstr "Biographie"
+
+msgid "Important notice"
+msgstr "Important"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Soyez prudent par rapport aux informations que vous inscrivez dans votre profil, étant donné que ceci peut être accessible de tous (même de ceux que vous ne voulez pas)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Tout n'est pas privé sur XMPP, entre autres votre profil public."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Il est fortement recommandé de définir une photo de profil (%s maximum), par exemple une photo de vous ou une image vous représentant. Cela vous permet d'être facilement identifié par vos amis."
+
+msgid "Save"
+msgstr "Enregistrer"
+
+msgid "Cancel"
+msgstr "Annuler"
+
+msgid "Edit options"
+msgstr "Éditer les options"
+
+msgid "Channel"
+msgstr "Canal"
+
+msgid "Commands"
+msgstr "Commandes"
+
+msgid "Sounds"
+msgstr "Sons"
+
+msgid "Privacy"
+msgstr "Vie privée"
+
+msgid "Message archiving"
+msgstr "Archivage des messages"
+
+msgid "Store a history of your chats"
+msgstr "Garder un historique des conversations"
+
+msgid "Geolocation"
+msgstr "Géolocalisation"
+
+msgid "Empty"
+msgstr "Vider"
+
+msgid "Empty channel"
+msgstr "Vider le canal"
+
+msgid "Persistent"
+msgstr "Persistant"
+
+msgid "Maximum notices"
+msgstr "Avis maximum"
+
+msgid "Account"
+msgstr "Compte"
+
+msgid "Change password"
+msgstr "Changer de mot de passe"
+
+msgid "Delete account"
+msgstr "Supprimer le compte"
+
+msgid "Old"
+msgstr "Ancien"
+
+msgid "New (2 times)"
+msgstr "Nouveau (2 fois)"
+
+msgid "Continue"
+msgstr "Continuer"
+
+msgid "To"
+msgstr "À"
+
+msgid "Close"
+msgstr "Fermer"
+
+msgid "unknown"
+msgstr "inconnu(e)"
+
+msgid "Unavailable"
+msgstr "Déconnecté(e)"
+
+msgid "is now"
+msgstr "est maintenant"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Patientez pendant que votre avatar est envoyé..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Et voilà ! Une nouvelle photo de profil !"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Le fichier image n'est pas pris en charge ou est trop gros."
+
+msgid "Reply"
+msgstr "Répondre"
+
+msgid "Error"
+msgstr "Erreur"
+
+msgid "Click here to solve the error"
+msgstr "Cliquez ici pour résoudre l'erreur"
+
+msgid "You"
+msgstr "Vous"
+
+msgid "Remove"
+msgstr "Enlever"
+
+msgid "Rename"
+msgstr "Renommer"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Bonjour, je suis %s, je souhaiterais vous ajouter comme ami."
+
+msgid "Smiley insertion"
+msgstr "Insertion d'émoticône"
+
+msgid "Change style"
+msgstr "Changer l'apparence"
+
+msgid "Text in bold"
+msgstr "Texte en gras"
+
+msgid "Text in italic"
+msgstr "Texte en italique"
+
+msgid "Underlined text"
+msgstr "Texte souligné"
+
+msgid "Save chat"
+msgstr "Enregistrer la discussion"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Cliquez sur le lien suivant pour obtenir l'historique de la discussion. Cliquez à nouveau pour le récupérer."
+
+msgid "This chat is empty!"
+msgstr "Cette discussion est vide !"
+
+msgid "Generate file!"
+msgstr "Générer le fichier !"
+
+msgid "Download file!"
+msgstr "Télécharger le fichier !"
+
+msgid "Clean current chat"
+msgstr "Nettoyer la discussion courante"
+
+msgid "View chat history"
+msgstr "Voir l'historique de discussion"
+
+msgid "Show user profile"
+msgstr "Afficher le profil de l'utilisateur"
+
+msgid "Add this contact to your friends"
+msgstr "Ajouter ce contact à vos amis"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Ajouter ce salon à vos favoris"
+
+msgid "All tabs"
+msgstr "Tous les onglets"
+
+msgid "Close this tab"
+msgstr "Fermer cet onglet"
+
+msgid "no subject defined for this room."
+msgstr "aucun sujet défini pour ce salon."
+
+msgid "Administration panel for this room"
+msgstr "Panneau d'administration du salon"
+
+msgid "Moderators"
+msgstr "Modérateurs"
+
+msgid "Participants"
+msgstr "Participants"
+
+msgid "Visitors"
+msgstr "Visiteurs"
+
+msgid "Manage favorite rooms"
+msgstr "Gérer les salons favoris"
+
+msgid "Change favorites"
+msgstr "Modifier les favoris"
+
+msgid "Search a room"
+msgstr "Chercher un salon"
+
+msgid "Select a favorite"
+msgstr "Sélectionnez un favori"
+
+msgid "Getting the name..."
+msgstr "Obtention du nom..."
+
+msgid "Gateway"
+msgstr "Passerelle"
+
+msgid "Name"
+msgstr "Nom"
+
+msgid "Room"
+msgstr "Salon"
+
+msgid "Add"
+msgstr "Ajouter"
+
+msgid "Edit"
+msgstr "Modifier"
+
+msgid "Search a room on"
+msgstr "Rechercher un salon sur"
+
+msgid "No room found on this server."
+msgstr "Aucun salon trouvé sur ce serveur."
+
+msgid "Service discovery"
+msgstr "Découverte des services"
+
+msgid "Server to query"
+msgstr "Serveur à interroger"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Désolé, mais l'entité n'a pas retourné de résultat !"
+
+msgid "Accounts"
+msgstr "Comptes"
+
+msgid "Authentications"
+msgstr "Authentifications"
+
+msgid "Automation"
+msgstr "Automatismes"
+
+msgid "Clients"
+msgstr "Clients"
+
+msgid "Collaboration"
+msgstr "Collaboration"
+
+msgid "Components"
+msgstr "Composants"
+
+msgid "Rooms"
+msgstr "Salons"
+
+msgid "Directories"
+msgstr "Annuaires"
+
+msgid "Gateways"
+msgstr "Passerelles"
+
+msgid "News"
+msgstr "Actualités"
+
+msgid "Hierarchy"
+msgstr "Hiérarchie"
+
+msgid "Proxies"
+msgstr "Proxies"
+
+msgid "Publication/Subscription"
+msgstr "Publication/Abonnement"
+
+msgid "Storage"
+msgstr "Stockage"
+
+msgid "Service offline or broken"
+msgstr "Service hors ligne ou cassé"
+
+msgid "Your inbox"
+msgstr "Votre boîte de réception"
+
+msgid "Available actions"
+msgstr "Actions disponibles"
+
+msgid "Clean"
+msgstr "Vider"
+
+msgid "New"
+msgstr "Nouveau"
+
+msgid "Received"
+msgstr "Reçus"
+
+msgid "Subject"
+msgstr "Sujet"
+
+msgid "Content"
+msgstr "Contenu"
+
+msgid "Send message"
+msgstr "Envoyer le message"
+
+msgid "Your inbox is empty."
+msgstr "Votre boîte de réception est vide."
+
+msgid "MUC administration"
+msgstr "Administration d'un MUC"
+
+msgid "You administrate this room"
+msgstr "Vous administrez ce salon"
+
+msgid "Enter new subject"
+msgstr "Entrez le nouveau sujet"
+
+msgid "Configuration"
+msgstr "Configuration"
+
+msgid "Authorizations"
+msgstr "Autorisations"
+
+msgid "Member list"
+msgstr "Liste des membres"
+
+msgid "Owner list"
+msgstr "Liste des propriétaires"
+
+msgid "Administrator list"
+msgstr "Liste des administrateurs"
+
+msgid "Outcast list"
+msgstr "Liste des bannis"
+
+msgid "Add an input"
+msgstr "Ajouter un champ"
+
+msgid "Destroy this MUC"
+msgstr "Détruire le MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Oui, détruisons-le !"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Votre ami prête attention à la conversation."
+
+msgid "Your friend is writing a message..."
+msgstr "Votre ami est en train de composer un message..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Votre ami a arrêté d'écrire un message."
+
+msgid "Your friend is doing something else."
+msgstr "Votre ami fait quelque-chose d'autre."
+
+msgid "Your friend closed the chat."
+msgstr "Votre ami a quitté la conversation."
+
+msgid "Requesting this service..."
+msgstr "Requête en cours..."
+
+msgid "Loading"
+msgstr "En attente"
+
+msgid "joined the chat room"
+msgstr "a rejoint le salon"
+
+msgid "left the chat room"
+msgstr "a quitté le salon"
+
+msgid "no status"
+msgstr "aucun statut"
+
+msgid "has been kicked"
+msgstr "a été éjecté"
+
+msgid "has been banned"
+msgstr "a été banni"
+
+msgid "no reason"
+msgstr "pas de raison"
+
+msgid "Communicate with the entire world!"
+msgstr "Communiquez avec le monde entier !"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Entrez en contact avec les millions de personnes qui utilisent le réseau XMPP comme vous le faites avec Jappix. Rejoignez-nous et restez libre !"
+
+msgid "Hi there!"
+msgstr "Salut toi !"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Bienvenue sur %1s, « %2s »."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Connectez-vous à votre compte XMPP existant ou créez-en un nouveau gratuitement !"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix est un projet libre de PostPro, une organisation à but non lucratif qui nous aide beaucoup."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Connectez-vous à votre compte XMPP existant. Vous pouvez aussi utiliser le %s pour rejoindre un salon."
+
+msgid "Previous"
+msgstr "Précédent"
+
+msgid "General"
+msgstr "Général"
+
+msgid "Advanced"
+msgstr "Avancé"
+
+msgid "Resource"
+msgstr "Ressource"
+
+msgid "Priority"
+msgstr "Priorité"
+
+msgid "Low"
+msgstr "Bas"
+
+msgid "Medium"
+msgstr "Moyen"
+
+msgid "High"
+msgstr "Haut"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Entrez le salon que vous voulez rejoindre ainsi que votre pseudo. Vous pouvez aussi revenir à la %s. "
+
+msgid "login page"
+msgstr "page de connexion"
+
+msgid "Share this link with your friends:"
+msgstr "Partagez ce lien avec vos amis :"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Créez un nouveau compte XMPP pour rejoindre vos amis sur votre propre nuage social. C'est super simple !"
+
+msgid "Required"
+msgstr "Requis"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Vous avez été inscrit, voici votre adresse XMPP :"
+
+msgid "Manager"
+msgstr "Gestionnaire"
+
+msgid "Project"
+msgstr "Projet"
+
+msgid "Encrypted"
+msgstr "Chiffré"
+
+msgid "Unencrypted"
+msgstr "Non chiffré"
+
+msgid "Where are you?"
+msgstr "Où êtes-vous ?"
+
+msgid "What's up with you?"
+msgstr "Quoi de neuf de votre côté ?"
+
+msgid "Fetching the social channel..."
+msgstr "Récupération du canal social..."
+
+msgid "You are synchronized with your network."
+msgstr "Vous êtes synchronisé(e) avec votre réseau."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Impossible d'envoyer des avis, vous ne pouvez qu'en recevoir !"
+
+msgid "Media viewer"
+msgstr "Visualisateur de médias"
+
+msgid "Browse"
+msgstr "Parcourir"
+
+msgid "Command"
+msgstr "Commande"
+
+msgid "Subscribe"
+msgstr "Souscrire"
+
+msgid "Join"
+msgstr "Rejoindre"
+
+msgid "Automatic"
+msgstr "Automatique"
+
+msgid "Search"
+msgstr "Rechercher"
+
+msgid "No result!"
+msgstr "Aucun résultat !"
+
+msgid "No notifications."
+msgstr "Pas de notifications."
+
+msgid "would like to add you as a friend."
+msgstr "voudrait vous ajouter comme ami."
+
+msgid "would like you to join this chatroom:"
+msgstr "voudrait que vous rejoigniez ce salon :"
+
+msgid "Do you accept?"
+msgstr "Acceptez-vous ?"
+
+msgid "Yes"
+msgstr "Oui"
+
+msgid "No"
+msgstr "Non"
+
+msgid "would like to get authorization."
+msgstr "voudrait obtenir une autorisation."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Voulez-vous voir les amis que %s vous suggère ?"
+
+msgid "Submit"
+msgstr "Soumettre"
+
+msgid "Client"
+msgstr "Client"
+
+msgid "System"
+msgstr "Système"
+
+msgid "Local time"
+msgstr "Heure locale"
+
+msgid "Comments"
+msgstr "Commentaires"
+
+msgid "User profile"
+msgstr "Profil de l'utilisateur"
+
+msgid "See his/her position on the globe"
+msgstr "Afficher sa position sur le globe"
+
+msgid "Confirm"
+msgstr "Confirmez"
+
+msgid "anonymous mode"
+msgstr "mode anonyme"
+
+msgid "Groups"
+msgstr "Groupes"
+
+msgid "Unclassified"
+msgstr "Non classés"
+
+msgid "Authorize"
+msgstr "Autoriser"
+
+msgid "Ask for authorization"
+msgstr "Demander l'autorisation"
+
+msgid "Unblock"
+msgstr "Débloquer"
+
+msgid "Prohibit"
+msgstr "Interdire"
+
+msgid "Block"
+msgstr "Bloquer"
+
+msgid "Chat"
+msgstr "Discussion"
+
+msgid "Groupchat"
+msgstr "Salon de discussion"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobile"
+
+msgid "Desktop"
+msgstr "Bureau"
+
+msgid "Mobile"
+msgstr "Mobile"
+
+msgid "Please wait..."
+msgstr "Patientez..."
+
+msgid "Please enable JavaScript"
+msgstr "Veuillez activer JavaScript"
+
+msgid "Your channel"
+msgstr "Votre canal"
+
+msgid "Channel of"
+msgstr "Canal de"
+
+msgid "More notices..."
+msgstr "Plus d'avis..."
+
+msgid "Attach a file"
+msgstr "Attacher un fichier"
+
+msgid "Send"
+msgstr "Envoyer"
+
+msgid "Unattach the file"
+msgstr "Détacher le fichier"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Une erreur est survenue lors de l'envoi de votre fichier : il peut être trop gros (%s maximum) ou interdit ! "
+
+msgid "Authorization failed"
+msgstr "Échec de l'autorisation"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Échec de l'inscription, choisissez un pseudo différent"
+
+msgid "Service unavailable"
+msgstr "Service indisponible"
+
+msgid "Internal server error, try later"
+msgstr "Erreur interne du serveur, essayez plus tard"
+
+msgid "Your form has been sent."
+msgstr "Votre formulaire a été soumis."
+
+msgid "Application"
+msgstr "Application"
+
+msgid "XMPP links"
+msgstr "Liens XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Ouvrir les liens XMPP avec Jappix"
+
+msgid "changed the subject to:"
+msgstr "a changé le sujet en :"
+
+msgid "Welcome!"
+msgstr "Bienvenue !"
+
+msgid "Friends"
+msgstr "Amis"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Bienvenue sur Jappix, votre propre nuage social !"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Avant de l'utiliser, vous aurez à changer quelques paramètres, rechercher vos amis et compléter votre profil."
+
+msgid "Enable notification sounds"
+msgstr "Activer les sons de notification"
+
+msgid "Share your position on the globe"
+msgstr "Partager votre position sur le globe"
+
+msgid "Offline friends"
+msgstr "Amis hors ligne"
+
+msgid "Don't hide offline friends"
+msgstr "Ne pas masquer les amis hors ligne"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Utilisez cet outil pour retrouver vos amis sur le serveur que vous utilisez, ou ajoutez-les plus tard."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Super boulot ! Maintenant, vous pouvez partager Jappix avec vos amis !"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Quand vous cliquerez sur le bouton d'enregistrement, l'éditeur de profil sera ouvert. Bonne socialisation !"
+
+msgid "Share Jappix on %s"
+msgstr "Partagez Jappix sur %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Utilise Jappix, une plateforme sociale ouverte. Je suis %s !"
+
+msgid "Unknown name"
+msgstr "Nom inconnu"
+
+msgid "Unknown country"
+msgstr "Pays inconnu"
+
+msgid "Click to enable"
+msgstr "Cliquez pour activer"
+
+msgid "Click to disable"
+msgstr "Cliquez pour désactiver"
+
+msgid "Installation"
+msgstr "Installation"
+
+msgid "Jappix installation"
+msgstr "Installation de Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Bienvenue dans l'installation de Jappix !"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Cet outil vous aidera à installer rapidement Jappix, le premier réseau social complet utilisant XMPP, sur votre serveur. Vous n'avez pas besoin d'avoir de connaissances techniques particulières.."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Jetons un coup d'œil aux étapes de l'installation :"
+
+msgid "Welcome"
+msgstr "Bienvenue"
+
+msgid "Storage configuration"
+msgstr "Configuration du stockage"
+
+msgid "Administrator account"
+msgstr "Compte administrateur"
+
+msgid "Main configuration"
+msgstr "Configuration principale"
+
+msgid "Hosts configuration"
+msgstr "Configuration des hôtes"
+
+msgid "Services installation"
+msgstr "Installation des services"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Si la langue courante n'est pas la vôtre (%1s), vous pouvez faire parler Jappix %2s ce sera sauvegardé."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Si vous voulez obtenir de l'aide à propos de l'installation et la configuration de Jappix, vous pouvez utiliser notre documentation, disponible à :"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Il est temps de créer votre propre nuage social : rendez-vous à l'étape suivante !"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix stocke les données persistantes (comme les fichiers partagés, les historiques des discussions et sa configuration) dans un dossier de stockage sécurisé."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix doit pouvoir écrire dans ce dossier pour y créer ses sous-répertoires. S'il ne le peut pas, vous devrez appliquer les droits à %1s ou changer le propriétaire à %2s (dépend de votre configuration)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Le dossier peut être écrit, vous pouvez continuer !"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix vous offre la possibilité de gérer votre configuration, installer des nouveaux modules et rechercher des mises à jour. C'est pourquoi vous devez créer un compte administrateur pour accéder au gestionnaire."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Quand Jappix sera installé, vous n'aurez qu'à cliquer sur le lien vers le gestionnaire sur la page d'accueil pour y accéder."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Oups, vous avez oublié quelque-chose ou les deux mots de passe ne correspondent pas !"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix a besoin que vous spécifiez quelques valeurs pour qu'il fonctionne. Corrigez les champs suivants (ou conservez les valeurs par défaut, qui sont suffisantes pour la plupart des gens)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Notez que si vous ne spécifiez pas une valeur obligatoire, elle sera automatiquement complétée par celle par défaut."
+
+msgid "User"
+msgstr "Utilisateur"
+
+msgid "Service"
+msgstr "Service"
+
+msgid "Service name"
+msgstr "Nom du service"
+
+msgid "Service description"
+msgstr "Description du service"
+
+msgid "Connection"
+msgstr "Connexion"
+
+msgid "Lock the host"
+msgstr "Vérrouiller l'hôte"
+
+msgid "Anonymous mode"
+msgstr "Mode anonyme"
+
+msgid "Registration allowed"
+msgstr "Inscription autorisée"
+
+msgid "Use a proxy"
+msgstr "Utiliser un proxy"
+
+msgid "Encryption"
+msgstr "Chiffrement"
+
+msgid "HTTPS storage"
+msgstr "Stockage en HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Forcer le HTTPS"
+
+msgid "Compression"
+msgstr "Compression"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Cette page vous permet de spécifier les hôtes par défaut auxquels Jappix se connectera. Vous pouvez garder les mêmes valeurs et continuer si vous souhaitez utiliser les hôtes du service officiel."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Peut-être que vous ne savez pas ce qu'est un serveur BOSH ? En fait, c'est un relai entre un client Jappix et un serveur XMPP, qui est nécessaire en raison de limitations techniques."
+
+msgid "Main host"
+msgstr "Hôte principal"
+
+msgid "Groupchat host"
+msgstr "Hôte de salons"
+
+msgid "Anonymous host"
+msgstr "Hôte anonyme"
+
+msgid "Directory host"
+msgstr "Hôte d'annuaire"
+
+msgid "BOSH host"
+msgstr "Hôte BOSH"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Vous pouvez installer quelques logiciels supplémentaires sur votre serveur, pour étendre les fonctionnalités de Jappix. Quelques autres pourraient être modifiés, en raison des restrictions de sécurité qui sont en place par défaut."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Pour réaliser cela, vous devez pouvoir accéder à la ligne de commande de votre serveur et y être connecté en tant qu'administrateur. Sachez que cela est facultatif, Jappix fonctionnera sans ces modules, mais quelques-unes de ses fonctionnalités seront indisponibles."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Après avoir terminé l'installation, Jappix va générer les fichiers de cache. Cela pourra être lent, attendez que l'application soit affichée et ne pressez aucun bouton."
+
+msgid "Thanks for using Jappix!"
+msgstr "Merci d'utiliser Jappix !"
+
+msgid "Next"
+msgstr "Suivant"
+
+msgid "Finish"
+msgstr "Finir"
+
+msgid "Check again"
+msgstr "Vérifier à nouveau"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Le dossier ne peut pas être écrit, appliquez les bonnes permissions au dossier %s."
+
+msgid "%s is installed on your system."
+msgstr "%s est installé sur votre système."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s n'est pas installé sur votre système, vous devriez installer %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "La limite PHP de la taille à l'envoi de fichiers est suffisante (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "La limite PHP de la taille à l'envoi de fichiers (%1s) n'est pas suffisante, vous devriez la définir à %2s dans le %3s."
+
+msgid "Jappix manager"
+msgstr "Gestionnaire de Jappix"
+
+msgid "Manager access"
+msgstr "Accès au gestionnaire"
+
+msgid "Statistics"
+msgstr "Statistiques"
+
+msgid "Hosts"
+msgstr "Hôtes"
+
+msgid "Design"
+msgstr "Apparence"
+
+msgid "Repeat"
+msgstr "Répéter"
+
+msgid "All"
+msgstr "Tout"
+
+msgid "Horizontal"
+msgstr "Horizontal"
+
+msgid "Vertical"
+msgstr "Vertical"
+
+msgid "Center"
+msgstr "Centrer"
+
+msgid "Left"
+msgstr "Gauche"
+
+msgid "Right"
+msgstr "Droite"
+
+msgid "Top"
+msgstr "Haut"
+
+msgid "Bottom"
+msgstr "Bas"
+
+msgid "Adapt"
+msgstr "Adapter"
+
+msgid "Color"
+msgstr "Couleur"
+
+msgid "Users"
+msgstr "Utilisateurs"
+
+msgid "Updates"
+msgstr "Mises à jour"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Ceci est une zone à accès limité : seules les personnes autorisées peuvent gérer ce nœud Jappix."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Utilisez le formulaire ci-dessous pour vous connecter au panneau d'administration."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Pour améliorer la sécurité, les sessions sont limitées dans le temps, et quand votre navigateur sera fermé, vous serez déconnecté."
+
+msgid "Credentials"
+msgstr "Identifiants"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Vous avez été déconnecté. Au revoir !"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Oups, vous n'avez pas pû être reconnu comme administrateur valide. Vérifiez vos identifiants !"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Des statistiques basiques sont calculées par Jappix à propos de choses relativement importantes, vous pouvez les trouver ci-dessous."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Modifiez la configuration de votre nœud Jappix avec cet outil."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Modifiez les hôtes XMPP que ce nœud Jappix peut servir avec cet outil."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Tous les fichiers stockés de ce nœud peuvent être gérés avec cet outil : sélectionnez un sous-dossier et commencez à éditer son contenu !"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix est entièrement personnalisable : vous pouvez modifier son apparence ici-même."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Ce n'est pas une image valide, utilisez du PNG, GIF ou JPG !"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "L'image n'a pas pû être reçue, pourriez-vous réessayer ?"
+
+msgid "Your image was added to the list!"
+msgstr "Votre image a été ajoutée à la liste !"
+
+msgid "Changes saved!"
+msgstr "Les changements ont été sauvegardés !"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Vous pouvez définir plus d'un administrateur pour ce nœud Jappix. Vous pouvez aussi changer un mot de passe avec cet outil."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Mettez à jour votre nœud Jappix avec cet outil, ou vérifiez si une nouvelle est disponible. Des informations à propos de la dernière version sont aussi affichées (en anglais)."
+
+msgid "Access statistics"
+msgstr "Statistiques des accès"
+
+msgid "Share statistics"
+msgstr "Statistiques des partages"
+
+msgid "Other statistics"
+msgstr "Autres statistiques"
+
+msgid "January"
+msgstr "Janvier"
+
+msgid "February"
+msgstr "Février"
+
+msgid "March"
+msgstr "Mars"
+
+msgid "April"
+msgstr "Avril"
+
+msgid "May"
+msgstr "Mai"
+
+msgid "June"
+msgstr "Juin"
+
+msgid "July"
+msgstr "Juillet"
+
+msgid "August"
+msgstr "Août"
+
+msgid "September"
+msgstr "Septembre"
+
+msgid "October"
+msgstr "Octobre"
+
+msgid "November"
+msgstr "Novembre"
+
+msgid "December"
+msgstr "Décembre"
+
+msgid "Monday"
+msgstr "Lundi"
+
+msgid "Tuesday"
+msgstr "Mardi"
+
+msgid "Wednesday"
+msgstr "Mercredi"
+
+msgid "Thursday"
+msgstr "Jeudi"
+
+msgid "Friday"
+msgstr "Vendredi"
+
+msgid "Saturday"
+msgstr "Samedi"
+
+msgid "Sunday"
+msgstr "Dimanche"
+
+msgid "Total"
+msgstr "Total"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Historiques"
+
+msgid "Music"
+msgstr "Musique"
+
+msgid "Backgrounds"
+msgstr "Fonds"
+
+msgid "Share"
+msgstr "Partage"
+
+msgid "Background"
+msgstr "Fond"
+
+msgid "Notice"
+msgstr "Annonce"
+
+msgid "Your design preferences have been saved!"
+msgstr "Vos préférences d'apparence ont été enregistrées !"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Veuillez vérifier vos champs : quelque-chose manque !"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Changez l'apparence de votre nœud Jappix avec cet outil. Vous pouvez soit définir une couleur personnalisée, soit envoyer une image. Laissez votre créativité s'exprimer !"
+
+msgid "Use default background"
+msgstr "Utiliser le fond par défaut"
+
+msgid "Use your own image"
+msgstr "Utiliser votre propre image"
+
+msgid "Select a background to use and change the display options."
+msgstr "Sélectionnez un fond à utiliser et modifiez les options d'affichage."
+
+msgid "Use your own color"
+msgstr "Utiliser votre propre couleur"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Entrez la valeur hexadécimale de la couleur que vous voulez utiliser comme fond."
+
+msgid "Manage backgrounds"
+msgstr "Gérer les fonds"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Vous pouvez ajouter un nouveau fond à la liste avec cet outil. Veillez à envoyer une image valide."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Si vous voulez enlever des fonds, utilisez le navigateur ci-dessous."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Définissez, avec cet outil, une annonce de page d'accueil pour tous vos utilisateurs, comme un avertissement, un message important ou une publicité."
+
+msgid "Simple notice"
+msgstr "Annonce simple"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Cette annonce ne nécessite qu'un texte simple pour être affiché, mais aucun code n'est autorisé !"
+
+msgid "Advanced notice"
+msgstr "Annonce avancée"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Vous pouvez personnaliser votre annonce avec du code intégré (HTML, CSS et JS), mais vous devez coder l'apparence."
+
+msgid "Available updates"
+msgstr "Mises à jour disponibles"
+
+msgid "What's new?"
+msgstr "Quoi de nouveau ?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Vos dossiers de stockage ne peuvent être écrits, pourriez-vous appliquer les bons droits ?"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s pourrait causer des problèmes au proxy, veuillez augmenter la valeur de %2s à %3s !"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Vous utilisez une version de développement de Jappix. Mettez-la à jour à travers notre dépôt en exécutant : %s. "
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Une nouvelle version de Jappix est disponible ! Jetez un coup d'œil à ce qui est nouveau et lancez la mise à jour !"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Votre version n'est pas à jour. Mettez-la à niveau maintenant vers %s en cliquant ici !"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Votre version semble être à jour, mais vous pouvez vérifier les mises à jour manuellement en cliquant ici."
+
+msgid "Check for updates"
+msgstr "Rechercher des mises à jour"
+
+msgid "Update in progress"
+msgstr "Mise à jour en cours"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix a été mis à jour : vous utilisez à présent la dernière version. Amusez-vous bien !"
+
+msgid "The update has failed! Please try again later."
+msgstr "La mise à jour a échoué ! Veuillez réessayer plus tard."
+
+msgid "Downloading package..."
+msgstr "Téléchargement du paquet..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Suppression des fichiers systèmes de Jappix..."
+
+msgid "Extracting package..."
+msgstr "Extraction du paquet..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Regénération de l'arbre de stockage..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix est maintenant à jour !"
+
+msgid "Aborted: socket error!"
+msgstr "Avorté : erreur de connexion !"
+
+msgid "Aborted: buffer error!"
+msgstr "Avorté : erreur de tampon !"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Avorté : tout ne peut être écrit !"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Avorté : paquet impossible à extraire !"
+
+msgid "Visits"
+msgstr "Visites"
+
+msgid "Daily"
+msgstr "Quotidien"
+
+msgid "Weekly"
+msgstr "Hebdomadaire"
+
+msgid "Monthly"
+msgstr "Mensuel"
+
+msgid "Yearly"
+msgstr "Annuelle"
+
+msgid "Size"
+msgstr "Taille"
+
+msgid "Clean everything"
+msgstr "Tout nettoyer"
+
+msgid "Purge cache"
+msgstr "Purger le cache"
+
+msgid "Purge logs"
+msgstr "Purger les historiques"
+
+msgid "Purge updates"
+msgstr "Purger les mises à jour"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Le dossier de stockage que vous vouliez nettoyer est maintenant vide !"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Gardez votre nœud Jappix frais et rapide, nettoyez les dossiers de stockage régulièrement !"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Envoyez votre musique (Ogg Vorbis, MP3 ou WAV) pour pouvoir l'écouter depuis Jappix !"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Le fichier que vous souhaitez envoyer doit être plus petit que %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Restez informé de ce que vos utilisateurs stockent sur votre serveur, et supprimez le contenu indésirable avec cet outil."
+
+msgid "Title"
+msgstr "Titre"
+
+msgid "Artist"
+msgstr "Artiste"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Fichier"
+
+msgid "Upload"
+msgstr "Envoyer"
+
+msgid "The folder is empty."
+msgstr "Le dossier est vide."
+
+msgid "The music could not be received, please retry!"
+msgstr "La musique n'a pas pû être reçue, veuillez réessayer !"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Ce n'est pas un fichier musical valide, encodez-le en Ogg Vorbis, MP3 ou WAV !"
+
+msgid "Your music has been added!"
+msgstr "Votre musique a été ajoutée !"
+
+msgid "The selected elements have been removed."
+msgstr "Les éléments sélectionnés ont été enlevés."
+
+msgid "You must select elements to remove!"
+msgstr "Vous devez sélectionner des éléments à effacer !"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Ajoutez un nouvel utilisateur avec cet outil, ou changez un mot de passe (entrez un nom d'utilisateur existant). Veillez à utiliser un mot de passe fort !"
+
+msgid "Manage"
+msgstr "Gérer"
+
+msgid "List"
+msgstr "Liste"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Supprimez des utilisateurs avec cet outil. Notez que vous ne pouvez pas supprimer un utilisateur s'il est le seul restant."
+
+msgid "The user has been added!"
+msgstr "L'utilisateur a été ajouté !"
+
+msgid "The chosen users have been removed."
+msgstr "Les utilisateurs sélectionnés ont été enlevés."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Vous devez sélectionner un ou plusieurs utilisateurs à enlever !"
+
+msgid "Yesterday"
+msgstr "Hier"
+
+msgid "%s days ago"
+msgstr "Il y a %s jours"
+
+msgid "User currently active"
+msgstr "Utilisateur actuellement actif"
+
+msgid "Last seen: %s"
+msgstr "Dernièrement vu(e) : %s"
+
+msgid "Inactive since: %s"
+msgstr "Inactif depuis : %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Votre ami(e) n'a pas l'air d'avoir reçu(e) votre/vos messages(s) !"
+
+msgid "Static content server"
+msgstr "Serveur de contenu statique"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Ceci est le serveur de contenu statique pour %1s, « %2s »."
+
+msgid "Suggested friends"
+msgstr "Amis suggérés"
+
+msgid "Check all"
+msgstr "Tout cocher"
+
+msgid "Uncheck all"
+msgstr "Tout décocher"
+
+msgid "Choose"
+msgstr "Choisir"
+
+msgid "List name"
+msgstr "Nom de liste"
+
+msgid "Allow"
+msgstr "Autoriser"
+
+msgid "Deny"
+msgstr "Interdire"
+
+msgid "Group"
+msgstr "Groupe"
+
+msgid "Subscription"
+msgstr "Abonnement"
+
+msgid "Both"
+msgstr "Les deux"
+
+msgid "From"
+msgstr "De"
+
+msgid "Everybody"
+msgstr "Tout le monde"
+
+msgid "Send messages"
+msgstr "Envoyer des messages"
+
+msgid "Send queries"
+msgstr "Envoyer des requêtes"
+
+msgid "See my status"
+msgstr "Voir mon statut"
+
+msgid "Send his/her status"
+msgstr "Envoyer son statut"
+
+msgid "Everything"
+msgstr "Tout"
+
+msgid "Item"
+msgstr "Élément"
+
+msgid "Order"
+msgstr "Ordre"
+
+msgid "Active for this session"
+msgstr "Actif pour cette session"
+
+msgid "Always active"
+msgstr "Toujours actif"
+
+msgid "User directory"
+msgstr "Annuaire des utilisateurs"
+
+msgid "Search a friend"
+msgstr "Chercher un ami"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "La fonction demandée n'est pas implémentée par l'entité de destination, et n'a donc pas pu être traitée."
+
+msgid "This is a repeat from %s"
+msgstr "C'est une répétition depuis %s"
+
+msgid "Loading comments..."
+msgstr "Chargement des commentaires..."
+
+msgid "Type your comment here..."
+msgstr "Entrez votre commentaire..."
+
+msgid "Could not get the comments!"
+msgstr "Commentaires non récupérés !"
+
+msgid "Show comments"
+msgstr "Afficher les commentaires"
+
+msgid "Send him/her a message"
+msgstr "Lui envoyer un message"
+
+msgid "Start a chat with him/her"
+msgstr "Commencer une discussion avec lui/elle"
+
+msgid "Media integration"
+msgstr "Intégration des médias"
+
+msgid "Comments locked!"
+msgstr "Commentaires verrouillés !"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Entrez quelque-chose que vous souhaitez partager avec vos amis..."
+
+msgid "changed his/her nickname to %s"
+msgstr "porte %s comme nouveau pseudo"
+
+msgid "commented an item you follow: “%s”."
+msgstr "a commenté un élément que vous suivez : « %s »."
+
+msgid "Hide"
+msgstr "Masquer"
+
+msgid "liked your post: “%s”."
+msgstr "a aimé votre publication : « %s »."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "vous a cité quelque-part : « %s »."
+
+msgid "published on your wall: “%s”."
+msgstr "a publié sur votre mur : « %s »."
+
+msgid "tagged you in a photo (%s)."
+msgstr "vous a marqué dans une photo (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "vous a marqué dans une vidéo (%s)."
+
+msgid "Show"
+msgstr "Afficher"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Besoin d'aide ? Vous feriez mieux de lire notre page de documentation à propos de comment compléter ce formulaire !"
+
+msgid "Pubsub host"
+msgstr "Hôte Pubsub"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix est une plateforme sociale géniale, accessible de n'importe où, n'importe quand, et qui vous permet de communiquer avec qui vous voulez. "
+
+msgid "Manager link"
+msgstr "Lien du gestionnaire"
+
+msgid "User uploads server"
+msgstr "Serveur d'envois des utilisateurs"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Ceci est le serveur d'envois des utilisateurs pour %1s, « %2s »."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Vous pouvez appliquez votre propre logo pour votre service et ainsi remplacer celui par défaut. Faites attention à la taille et la couleur dominante de chaque logo !"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Envoyez chaque logo avec la taille maximum en pixel que nous vous recommandons."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Ce n'est pas une image valide, veuillez utiliser le format PNG !"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Le logo de votre service a été changé avec succès !"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Le format de votre logo doit être PNG. Laissez un champ vide et le logo correspondant ne sera pas changé."
+
+msgid "Remove this logo"
+msgstr "Supprimer ce logo"
+
+msgid "View this logo"
+msgstr "Visualiser ce logo"
+
+msgid "Send a file"
+msgstr "Envoi d'un fichier"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Une fois envoyé, votre ami sera invité à télécharger le fichier."
+
+msgid "Groupchats to join"
+msgstr "Salons à rejoindre"
+
+msgid "Purge sent files"
+msgstr "Purger les fichiers envoyés"
+
+msgid "would like to send you a file: “%s”."
+msgstr "voudrait vous envoyer un fichier : « %s »."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "a accepté de recevoir votre fichier : « %s »."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "a refusé de recevoir votre fichier : « %s »."
+
+msgid "could not receive your file: “%s”."
+msgstr "n'a pas pu recevoir votre fichier : « %s »."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "a reçu une demande d'échange de fichier : « %s »."
+
+msgid "Available shortcuts:"
+msgstr "Raccourcis disponibles :"
+
+msgid "%s removes the chat logs"
+msgstr "%s efface l'historique de la discussion"
+
+msgid "%s joins a groupchat"
+msgstr "%s rejoint un salon"
+
+msgid "%s closes the chat"
+msgstr "%s ferme la discussion"
+
+msgid "%s shows the user profile"
+msgstr "%s affiche le profil de l'utilisateur"
+
+msgid "%s sends a message to the room"
+msgstr "%s envoie un message au salon"
+
+msgid "%s changes your nickname"
+msgstr "%s modifie votre pseudonyme"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s envoie un message à quelqu'un du salon"
+
+msgid "%s changes the room topic"
+msgstr "%s modifie le sujet du salon"
+
+msgid "%s kicks an user of the room"
+msgstr "%s éjecte un utilisateur du salon"
+
+msgid "%s bans an user of the room"
+msgstr "%s banni un utilisateur du salon"
+
+msgid "%s invites someone to join the room"
+msgstr "%s invite quelqu'un à rejoindre le salon"
+
+msgid "Social channel, chat and more."
+msgstr "Canal social, tchat et plus."
+
+msgid "Create your public profile."
+msgstr "Créez votre profil public."
+
+msgid "A mini-chat for your website."
+msgstr "Un mini-tchat pour votre site."
+
+msgid "Get Jappix, get support."
+msgstr "Obtenez Jappix, recevez de l'aide."
+
+msgid "Statistics around Jappix."
+msgstr "Statistiques sur Jappix."
+
+msgid "Download Jappix for free."
+msgstr "Téléchargez gratuitement Jappix."
+
+msgid "Find a public Jappix node."
+msgstr "Trouvez un nœud Jappix public."
+
+msgid "Public profile"
+msgstr "Profil public"
+
+msgid "Your profile anywhere on the Web."
+msgstr "Votre profil partout sur le Web."
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr "%s est un service de Jappix.com qui rend votre profil XMPP public. Il est plus facile de le partager. Aucun compte XMPP n'est requis pour voir votre canal social, votre position actuelle et vos informations de contact."
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr "De plus, chaque photo que vous publiez dans votre canal social est ajoutée à un magnifique journal de vos photos. Vous pouvez à présent voir les photos que vous avez partagées année par année."
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr "Vous pouvez aussi utiliser votre avatar XMPP comme un avatar unique pour tout site, blog et forum que vous utilisez. Quand vous le changez sur XMPP, le nouvel avatar apparaît partout. Quelle innovation géniale !"
+
+msgid "Yay, let's create my public profile!"
+msgstr "Ouais, créons mon profil public !"
+
+msgid "Enable my public profile"
+msgstr "Activer mon profil public"
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix est une plateforme sociale à but non lucratif, accessible n'importe où, n'importe quand pour communiquer avec qui vous voulez."
+
+#~ msgid "See"
+#~ msgstr "Voir"
+
+#~ msgid "Use default logo"
+#~ msgstr "Utiliser le logo par défaut"
+
+#~ msgid "Use your own logo"
+#~ msgstr "Utiliser votre propre logo"
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr "Le format d'image recommandé est PNG. Laisser un champ vide ne changera pas le logo correspondant."
diff --git a/jappixmini/jappix/lang/hu/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/hu/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..6523744
Binary files /dev/null and b/jappixmini/jappix/lang/hu/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/hu/LC_MESSAGES/main.po b/jappixmini/jappix/lang/hu/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..89e5157
--- /dev/null
@@ -0,0 +1,1870 @@
+# Hungarian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:41+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "A JavaScript hiányzik a böngésződből, anélkül nem tudod használni a Jappixot! Kérlek javítsd."
+
+msgid "An open social network"
+msgstr "A nyílt szociális hálózat."
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "A Jappix hálózati probléma miatt megszakadt, hiba vagy rossz bejelentkezés (ellenőrízd helyesen töltötted-e ki az adatokat). Elnézést a kellemetlenségért!"
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Az elemek listája ezen a szerveren nem elérhető!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "A jelszavad megváltozott. Mostmár be tudsz jelentkezni a fiókodba az új adatokkal."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Az XMPP fiókod törölve, szia!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Sikeresen kijelentkeztél az XMPP fiókodból, további kellemes napot!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "A szoba ahova csatlakoztál még nem létezik. Előbb létre kell hoznod!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "A csoportos beszélgetést törölték, most valaki más létre tudja hozni."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "A felhasználó akit keresel, nincs a szobában!"
+
+msgid "Please enter the group chat address to join."
+msgstr "Kérlek add meg a csoportos beszélgetés címét a csatlakozáshoz."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Adj meg egy becenevet, hogy belépj a %s szobába."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Ez a szoba (%s) jelszóval védett."
+
+msgid "Your browser is out of date!"
+msgstr "A böngésződ régi, elavult."
+
+msgid "Last %s version is better!"
+msgstr "Az utolsó %s verzió jobb!"
+
+msgid "Login"
+msgstr "Bejelentkezés"
+
+msgid "Register"
+msgstr "Regisztráció"
+
+msgid "Here we go!"
+msgstr "Indulhatunk is!"
+
+msgid "Server"
+msgstr "Szerver"
+
+msgid "Password"
+msgstr "Jelszó"
+
+msgid "Remember me"
+msgstr "Emlékezz rám"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Ez az eszköz le van tiltva, nem tudod használni!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Hálózati hiba miatt a kapcsolat megszakadt. Most mit szeretnél tenni?"
+
+msgid "Reconnect"
+msgstr "Újrakapcsolódás"
+
+msgid "Messages"
+msgstr "Üzenetek"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Beállítások"
+
+msgid "Disconnect"
+msgstr "Kijelentkezés"
+
+msgid "Filter"
+msgstr "Szűrő"
+
+msgid "Add a friend"
+msgstr "Barát hozzáadása"
+
+msgid "Your groupchats"
+msgstr "Csoportos beszélgetéseid"
+
+msgid "Manage your favorite groupchats"
+msgstr "A kedvenc csoportos beszélgetéseid menedzselése"
+
+msgid "More stuff"
+msgstr "Több dolog"
+
+msgid "Show all friends"
+msgstr "Minden barát mutatása"
+
+msgid "Only show connected friends"
+msgstr "Csak a csatlakozott barátok mutatása"
+
+msgid "Message archives"
+msgstr "Archivált üzenetek"
+
+msgid "Date"
+msgstr "Dátum"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Kérlek válassz ki egy barátot, hogy lásd a beszélgetési előzményeket"
+
+msgid "Nothing found for: %s"
+msgstr "Nem található: %s"
+
+msgid "A short message?"
+msgstr "Egy rövid üzenet?"
+
+msgid "How are you?"
+msgstr "Hogy vagy?"
+
+msgid "What are you doing?"
+msgstr "Mit csinálsz?"
+
+msgid "Join a chat"
+msgstr "Csatlakozás egy beszélgetéshez"
+
+msgid "Status"
+msgstr "Státusz"
+
+msgid "Available"
+msgstr "Elérhető"
+
+msgid "Talkative"
+msgstr "Beszédes"
+
+msgid "Away"
+msgstr "Távol"
+
+msgid "Not available"
+msgstr "Nem elérhető"
+
+msgid "Busy"
+msgstr "Elfoglalt"
+
+msgid "Mood"
+msgstr "Hangulat"
+
+msgid "None"
+msgstr "Nincs"
+
+msgid "Crazy"
+msgstr "Bolond"
+
+msgid "Excited"
+msgstr "Izgatott"
+
+msgid "Playful"
+msgstr "Játékos"
+
+msgid "Happy"
+msgstr "Boldog"
+
+msgid "Shocked"
+msgstr "Döbbent"
+
+msgid "Hot"
+msgstr "Pimasz"
+
+msgid "Sad"
+msgstr "Szomorú"
+
+msgid "Amorous"
+msgstr "Szerelmes"
+
+msgid "Confident"
+msgstr "Magabiztos"
+
+msgid "Activity"
+msgstr "Tevékenység"
+
+msgid "Chores"
+msgstr "Házimunka"
+
+msgid "Drinking"
+msgstr "Iszik"
+
+msgid "Eating"
+msgstr "Eszik"
+
+msgid "Exercising"
+msgstr "Testedzés"
+
+msgid "Grooming"
+msgstr "Szépségápolás"
+
+msgid "Appointment"
+msgstr "Találkozó"
+
+msgid "Inactive"
+msgstr "Tétlen"
+
+msgid "Relaxing"
+msgstr "Pihen"
+
+msgid "Talking"
+msgstr "Beszélgetés"
+
+msgid "Traveling"
+msgstr "Utazás"
+
+msgid "Working"
+msgstr "Dolgozik"
+
+msgid "View profile"
+msgstr "Profil megtekintése"
+
+msgid "Repeat this notice"
+msgstr "Értesítés megismétlése"
+
+msgid "Remove this notice"
+msgstr "Értesítés eltávolítása"
+
+msgid "Your profile"
+msgstr "A te profilod"
+
+msgid "Identity"
+msgstr "Személyazonosság"
+
+msgid "Profile image"
+msgstr "Profilkép"
+
+msgid "Others"
+msgstr "Mások /Egyebek"
+
+msgid "Personal"
+msgstr "Személyes"
+
+msgid "Complete name"
+msgstr "Teljes név"
+
+msgid "Nickname"
+msgstr "Felhasználónév"
+
+msgid "First name"
+msgstr "Keresztnév"
+
+msgid "Last name"
+msgstr "Vezetéknév"
+
+msgid "Date of birth"
+msgstr "Születési dátum"
+
+msgid "Contact"
+msgstr "Kapcsolat"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefon"
+
+msgid "Website"
+msgstr "Honlap"
+
+msgid "Current"
+msgstr "Jelenlegi"
+
+msgid "Delete"
+msgstr "Töröl"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Milyen kár! Nincs profilkép társítva a személyi igazolványodhoz."
+
+msgid "Address"
+msgstr "Cím"
+
+msgid "Street"
+msgstr "Utca"
+
+msgid "City"
+msgstr "Város"
+
+msgid "Postal code"
+msgstr "Irányítószám"
+
+msgid "Country"
+msgstr "Ország"
+
+msgid "Biography"
+msgstr "Életrajz"
+
+msgid "Important notice"
+msgstr "Fontos értesítés"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Légy óvatos az információkkal amiket megadsz a profilodban, mert bárki hozzáférhet (olyan is akit lehet hogy nem akarsz)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Nem minden privát jellegű az XMPP-n, ez is egy ilyen dolog, a te publikus profilod (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Erősen ajánlott, hogy feltölts egy profilképet (%s maximum), mondjuk egy képet rólad, mert így a barátaid könnyebben felismernek. "
+
+msgid "Save"
+msgstr "Mentés"
+
+msgid "Cancel"
+msgstr "Mégse"
+
+msgid "Edit options"
+msgstr "Opciók szerkeztése"
+
+msgid "Channel"
+msgstr "Csatorna"
+
+msgid "Commands"
+msgstr "Parancsok"
+
+msgid "Sounds"
+msgstr "Hangok"
+
+msgid "Privacy"
+msgstr "Adatvédelem"
+
+msgid "Message archiving"
+msgstr "Üzenet archiválása"
+
+msgid "Store a history of your chats"
+msgstr "Korábbi beszélgetések tárolása"
+
+msgid "Geolocation"
+msgstr "Tartózkodási hely"
+
+msgid "Empty"
+msgstr "Üres"
+
+msgid "Empty channel"
+msgstr "Üres csatorna"
+
+msgid "Persistent"
+msgstr "Tartós"
+
+msgid "Maximum notices"
+msgstr "Maximális értesítés"
+
+msgid "Account"
+msgstr "Fiók"
+
+msgid "Change password"
+msgstr "Jelszó módosítása"
+
+msgid "Delete account"
+msgstr "Fiók törlése"
+
+msgid "Old"
+msgstr "Régi"
+
+msgid "New (2 times)"
+msgstr "Új (2-szer)"
+
+msgid "Continue"
+msgstr "Folytatás"
+
+msgid "To"
+msgstr "Címzett"
+
+msgid "Close"
+msgstr "Bezárás"
+
+msgid "unknown"
+msgstr "nem ismert"
+
+msgid "Unavailable"
+msgstr "Nem elérhető"
+
+msgid "is now"
+msgstr "most"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Kérlek várj amíg az avatar képed feltöltődik... "
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Kész is! Egy szép új profilkép!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Nem támogatott képfájl vagy túl nagy."
+
+msgid "Reply"
+msgstr "Válaszolás"
+
+msgid "Error"
+msgstr "Hiba"
+
+msgid "Click here to solve the error"
+msgstr "Kattints ide a hiba megoldásához"
+
+msgid "You"
+msgstr "Te"
+
+msgid "Remove"
+msgstr "Eltávolítás"
+
+msgid "Rename"
+msgstr "Átnevezés"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Szia, %s vagyok, és szeretnélek hozzáadni a barátaimhoz."
+
+msgid "Smiley insertion"
+msgstr "Hangulatjel beszúrása"
+
+msgid "Change style"
+msgstr "Stílus megváltoztatása"
+
+msgid "Text in bold"
+msgstr "Félkövér "
+
+msgid "Text in italic"
+msgstr "Dőlt"
+
+msgid "Underlined text"
+msgstr "Aláhúzott"
+
+msgid "Save chat"
+msgstr "Beszélgetés mentése"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Kattints a következő linkre, hogy megkapd a beszélgetési naplót, majd várj. Utána kattints újra a fájl mentéséhez."
+
+msgid "This chat is empty!"
+msgstr "Ez a beszélgetés üres!"
+
+msgid "Generate file!"
+msgstr "Fájl generálása!"
+
+msgid "Download file!"
+msgstr "Fájl letöltése!"
+
+msgid "Clean current chat"
+msgstr "Aktuális beszélgetés törlése"
+
+msgid "View chat history"
+msgstr "Beszélgetés előzményeinek megnézése"
+
+msgid "Show user profile"
+msgstr "Felhasználói profil megmutatása"
+
+msgid "Add this contact to your friends"
+msgstr "Ezen kapcsolat hozzáadása a barátokhoz"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Csoportos beszélgetés hozzáadása a kedvencekhez"
+
+msgid "All tabs"
+msgstr "Minden lap"
+
+msgid "Close this tab"
+msgstr "Lap bezárása"
+
+msgid "no subject defined for this room."
+msgstr "nincs téma megadva ehhez a szobához."
+
+msgid "Administration panel for this room"
+msgstr "Adminisztrációs panel ehhez a szobához"
+
+msgid "Moderators"
+msgstr "Moderátorok"
+
+msgid "Participants"
+msgstr "Résztvevők"
+
+msgid "Visitors"
+msgstr "Látogatók"
+
+msgid "Manage favorite rooms"
+msgstr "Kedvenc szobák kezelése"
+
+msgid "Change favorites"
+msgstr "Kedvencek megváltoztatása"
+
+msgid "Search a room"
+msgstr "Szoba keresése"
+
+msgid "Select a favorite"
+msgstr "Kedvenc kiválasztása"
+
+msgid "Getting the name..."
+msgstr "Név megszerzése..."
+
+msgid "Gateway"
+msgstr "Átjáró"
+
+msgid "Name"
+msgstr "Név"
+
+msgid "Room"
+msgstr "Szoba"
+
+msgid "Add"
+msgstr "Hozzáad"
+
+msgid "Edit"
+msgstr "Szerkesztés"
+
+msgid "Search a room on"
+msgstr "Szoba keresése a"
+
+msgid "No room found on this server."
+msgstr "Ezen a szerveren nincs ilyen szoba"
+
+msgid "Service discovery"
+msgstr "Szolgáltatás megismerése"
+
+msgid "Server to query"
+msgstr "Szerver lekérdezése"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Bocs, de lekérdezés nem hozott eredményt!"
+
+msgid "Accounts"
+msgstr "Fiókok"
+
+msgid "Authentications"
+msgstr "Hitelesítések"
+
+msgid "Automation"
+msgstr "Automatikusan"
+
+msgid "Clients"
+msgstr "Kliensek"
+
+msgid "Collaboration"
+msgstr "Együttműködés"
+
+msgid "Components"
+msgstr "Komponensek"
+
+msgid "Rooms"
+msgstr "Szobák"
+
+msgid "Directories"
+msgstr "Könyvtárak"
+
+msgid "Gateways"
+msgstr "Átjárók"
+
+msgid "News"
+msgstr "Hírek"
+
+msgid "Hierarchy"
+msgstr "Hierarchia"
+
+msgid "Proxies"
+msgstr "Proxik"
+
+msgid "Publication/Subscription"
+msgstr "Publikációk/Feliratkozások"
+
+msgid "Storage"
+msgstr "Tároló"
+
+msgid "Service offline or broken"
+msgstr "A szolgáltatás nem elérhető, vagy lezárt"
+
+msgid "Your inbox"
+msgstr "Postaládád"
+
+msgid "Available actions"
+msgstr "Elérhető műveletek"
+
+msgid "Clean"
+msgstr "Tisztít"
+
+msgid "New"
+msgstr "Új"
+
+msgid "Received"
+msgstr "Fogadott"
+
+msgid "Subject"
+msgstr "Tárgy"
+
+msgid "Content"
+msgstr "Tartalom"
+
+msgid "Send message"
+msgstr "Üzenet küldése"
+
+msgid "Your inbox is empty."
+msgstr "A bejövő fiókod üres"
+
+msgid "MUC administration"
+msgstr "MUC adminisztráció"
+
+msgid "You administrate this room"
+msgstr "Te adminisztrálod ezt a szobát"
+
+msgid "Enter new subject"
+msgstr "Írd be a témát"
+
+msgid "Configuration"
+msgstr "Testreszabás"
+
+msgid "Authorizations"
+msgstr "Engedélyek"
+
+msgid "Member list"
+msgstr "Tag lista"
+
+msgid "Owner list"
+msgstr "Tulajdonos lista"
+
+msgid "Administrator list"
+msgstr "Adminisztrátor lista"
+
+msgid "Outcast list"
+msgstr "Letiltottak listája"
+
+msgid "Add an input"
+msgstr "Bemenet hozzáadása"
+
+msgid "Destroy this MUC"
+msgstr "MUC elpusztítása"
+
+msgid "Yes, let's do it!"
+msgstr "Igen, csináljuk!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "A barátod figyelemmel kíséri a beszélgetést."
+
+msgid "Your friend is writing a message..."
+msgstr "A barátod épp ír neked…"
+
+msgid "Your friend stopped writing a message."
+msgstr "A barátod abbahagyta az üzenet írását."
+
+msgid "Your friend is doing something else."
+msgstr "A barátod valami mást csinál."
+
+msgid "Your friend closed the chat."
+msgstr "A barátod bezárta a beszélgetést."
+
+msgid "Requesting this service..."
+msgstr "Szolgáltatás kérése..."
+
+msgid "Loading"
+msgstr "Betöltés"
+
+msgid "joined the chat room"
+msgstr "csatlakozás a szobához"
+
+msgid "left the chat room"
+msgstr "a szoba elhagyása"
+
+msgid "no status"
+msgstr "nincs státusz"
+
+msgid "has been kicked"
+msgstr "kirúgva"
+
+msgid "has been banned"
+msgstr "kitiltva"
+
+msgid "no reason"
+msgstr "Nincs ok"
+
+msgid "Communicate with the entire world!"
+msgstr "Kommunikálj az egész világgal!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Segít, hogy kapcsolatban maradj emberek millióival akik az XMPP hálózatot használják, mint ahogy te is tudod a Jappix-el. Csatlakozz a közösséghez és maradj szabad!"
+
+msgid "Hi there!"
+msgstr "Szia!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Üdvözöljük %1son, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Jelentkezz be az XMPP fiókodba, vagy csinálj egy újat ingyen!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "A Jappix egy nyílt-forrású projekt a PostPro-tól, egy non-profit szervezettől ami nagy segítséggel van a számunkra."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Jelentkezz be az XMPP fiókodba. Használhatod a %s -t is, hogy csatlakozz egy csoportos beszélgetéshez."
+
+msgid "Previous"
+msgstr "Előző"
+
+msgid "General"
+msgstr "Általános"
+
+msgid "Advanced"
+msgstr "Haladó"
+
+msgid "Resource"
+msgstr "Forrás"
+
+msgid "Priority"
+msgstr "Prioritás"
+
+msgid "Low"
+msgstr "Alacsony"
+
+msgid "Medium"
+msgstr "Közepes"
+
+msgid "High"
+msgstr "Magas"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Add meg a csoportos beszélgetést amihez csatlakozni szeretnél és felhasználó nevet amit szeretnél. Vissza is tudsz menni a %s -hez."
+
+msgid "login page"
+msgstr "bejelentkezés oldal"
+
+msgid "Share this link with your friends:"
+msgstr "Link megosztása a barátaiddal"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Regisztrálj egy új XMPP fiókot, hogy csatlakozz a barátaidhoz a saját szociális felhődben. Ez egyszerű!"
+
+msgid "Required"
+msgstr "Szükséges"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Sikeresen regisztráltál, ez az XMPP címed:"
+
+msgid "Manager"
+msgstr "Menedzser"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Titkosított"
+
+msgid "Unencrypted"
+msgstr "Titkosítatlan"
+
+msgid "Where are you?"
+msgstr "Hol vagy?"
+
+msgid "What's up with you?"
+msgstr "Mi a helyzet veled?"
+
+msgid "Fetching the social channel..."
+msgstr "Szociális csatorna hozzáadása..."
+
+msgid "You are synchronized with your network."
+msgstr "Szinkronizálva vagy a hálózatoddal."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Nem lehet küldeni semmit: csak fogadni tudsz!"
+
+msgid "Media viewer"
+msgstr "Média néző"
+
+msgid "Browse"
+msgstr "Tallózás"
+
+msgid "Command"
+msgstr "Parancs"
+
+msgid "Subscribe"
+msgstr "Feliratkozás"
+
+msgid "Join"
+msgstr "Egyesít"
+
+msgid "Automatic"
+msgstr "Automatikus"
+
+msgid "Search"
+msgstr "Keresés"
+
+msgid "No result!"
+msgstr "Nincs találat!"
+
+msgid "No notifications."
+msgstr "Nincs értesítés."
+
+msgid "would like to add you as a friend."
+msgstr "hozzá szeretne téged adni barátként"
+
+msgid "would like you to join this chatroom:"
+msgstr "szeretné hogy csatlakozz ehhez a szobához:"
+
+msgid "Do you accept?"
+msgstr "Elfogadod?"
+
+msgid "Yes"
+msgstr "Igen"
+
+msgid "No"
+msgstr "Nem"
+
+msgid "would like to get authorization."
+msgstr "szeretne engedélyt szeretne kapni."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Akarod-e látni azokat a barátokat, akiket %s ajáln?"
+
+msgid "Submit"
+msgstr "Küldés"
+
+msgid "Client"
+msgstr "Kliens"
+
+msgid "System"
+msgstr "Rendszer"
+
+msgid "Local time"
+msgstr "Helyi idő"
+
+msgid "Comments"
+msgstr "Hozzászólások"
+
+msgid "User profile"
+msgstr "Felhasználói profil"
+
+msgid "See his/her position on the globe"
+msgstr "Megnézem a pozícióját a földgömbön."
+
+msgid "Confirm"
+msgstr "Megerősítés"
+
+msgid "anonymous mode"
+msgstr "Névtelen mód"
+
+msgid "Groups"
+msgstr "Csoportok"
+
+msgid "Unclassified"
+msgstr "Osztályozatlan"
+
+msgid "Authorize"
+msgstr "Engedélyez"
+
+msgid "Ask for authorization"
+msgstr "Kérés engedélyezésre"
+
+msgid "Unblock"
+msgstr "Felold"
+
+msgid "Prohibit"
+msgstr "Tiltás"
+
+msgid "Block"
+msgstr "Lezár"
+
+msgid "Chat"
+msgstr "Beszélgetés"
+
+msgid "Groupchat"
+msgstr "Csoportos beszélgetés"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobil"
+
+msgid "Desktop"
+msgstr "Asztal"
+
+msgid "Mobile"
+msgstr "Mobil"
+
+msgid "Please wait..."
+msgstr "Kérlek várj..."
+
+msgid "Please enable JavaScript"
+msgstr "Kérlek engedélyezd a JavaScript-et"
+
+msgid "Your channel"
+msgstr "A te csatornád"
+
+msgid "Channel of"
+msgstr "Csatornája "
+
+msgid "More notices..."
+msgstr "Mégtöbb értesítés... "
+
+msgid "Attach a file"
+msgstr "Fájl csatolása"
+
+msgid "Send"
+msgstr "Küldés"
+
+msgid "Unattach the file"
+msgstr "Fájlcsatolás törlése"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Hiba történt a fájl feltöltése közben: talán túl nagy (%s maximum) vagy le van tiltva."
+
+msgid "Authorization failed"
+msgstr "Engedélyezési hiba"
+
+msgid "Registration failed, please choose a different username"
+msgstr "A regisztráció nem sikerült, kérlek válassz másik felhasználónevet."
+
+msgid "Service unavailable"
+msgstr "A szolgáltatás nem elérhető"
+
+msgid "Internal server error, try later"
+msgstr "Belső szerver hiba, kérlek próbáld újra később"
+
+msgid "Your form has been sent."
+msgstr "Az űrlapod elküldve."
+
+msgid "Application"
+msgstr "Alkalmazás"
+
+msgid "XMPP links"
+msgstr "XMPP linkek"
+
+msgid "Open XMPP links with Jappix"
+msgstr "XMPP linkek megnyitása Jappix-el"
+
+msgid "changed the subject to:"
+msgstr "tárgy megváltoztatása erre:"
+
+msgid "Welcome!"
+msgstr "Üdvözöljük!"
+
+msgid "Friends"
+msgstr "Barátok"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Üdvözlünk a Jappix-en, a saját szociális felhődben!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Mielőtt elkezdenéd használni, meg kell változtatnod néhány beállítást, keresned kell barátokat és kitöltened a profilodat."
+
+msgid "Enable notification sounds"
+msgstr "Értesítési hangok engedélyezése."
+
+msgid "Share your position on the globe"
+msgstr "Pozícióm megosztása a földgömbön"
+
+msgid "Offline friends"
+msgstr "Kijelentkezett barátok"
+
+msgid "Don't hide offline friends"
+msgstr "Ne rejtse el a kijelentkezett barátokat"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Használd ezt az eszközt hogy megtaláld a barátaidat a szerveren amit most használsz, vagy add hozzá őket később."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Nagyszerű! Most már meg tudod osztani a Jappix-et a barátaiddal!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Ha megnyomod a mentés gombot,  meg fog nyílni a profil szerkesztő. Jó szocializálódást!"
+
+msgid "Share Jappix on %s"
+msgstr "A Jappix megosztása a %s -en."
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Jappix-et, egy nyílt szociális platformot használok. %s vagyok!"
+
+msgid "Unknown name"
+msgstr "Ismeretlen név"
+
+msgid "Unknown country"
+msgstr "Ismeretlen ország"
+
+msgid "Click to enable"
+msgstr "Kattints az engedélyezéshez."
+
+msgid "Click to disable"
+msgstr "Kattints az elutasításhoz"
+
+msgid "Installation"
+msgstr "Telepítés"
+
+msgid "Jappix installation"
+msgstr "Jappix telepítése"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Üdvözöljük a Jappix telepítésében!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Ez az eszköz segít gyorsan telepíteni a Jappix-et, az első teljes értékű XMPP alapú szociális platformot a szerveredre. Nincs szükséged semmilyen technikai tudásra."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Nézzük, mik a telepítés lépései:"
+
+msgid "Welcome"
+msgstr "Üdvözöljük"
+
+msgid "Storage configuration"
+msgstr "Tároló konfigurálása"
+
+msgid "Administrator account"
+msgstr "Adminisztrációs fiók"
+
+msgid "Main configuration"
+msgstr "Fő beállítások"
+
+msgid "Hosts configuration"
+msgstr "Kiszolgáló konfiguráció"
+
+msgid "Services installation"
+msgstr "Szolgáltatás telepítés"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Ha az aktuális nyelv nem egyezik a tiéddel (%1s), át tudod állítani a Jappix-et hogy %2s beszéljen."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Ha problémád van a Jappix telepítésével és konfigurálásával, megnézheted a dokumentációt ami elérhető itt:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Itt az idő létrehozni a saját szociális felhődet, kezd az első lépéssel!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "A Jappix tárolja az állandó adatokat (mint a megosztott fájlok, beszélgetések naplózásai, saját zenék és konfigurációk), egy egyedi, biztosított mappában."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "A Jappix-nak tudnia kell írni ebbe a mappába, hogy létre tudjon hozni almappákat. Ha nem tud, be kell állítanod az írási jogot %1s vagy megváltoztatni a mappa tulajdonosát %2s -re (a konfigurációdtól függően)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "A mappa írható, már folytathatod!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix felajánlja a lehetőséget, hogy menedzseld a konfigurációd, telepíts új kiegészítőket, vagy keress frissítéseket. Ezért kell létrehoznod egy adminisztrátori fiókot, hogy hozzáférj ezekhez a beállításokhoz."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Ha telepítetted a Jappix-et, csak kattints a menedzser linkre a főoldalon, hogy hozzáférj."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Oppá, valamit elírtál, vagy a két jelszó nem egyezik!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "A Jappixnak szüksége van pár érték beállítására. Kérlek korrigáld az alábbi bemeneteket (vagy tartsd meg az alapértelmezetteket, amik a legtöbb ember számára ajánlottak)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Jegyezd meg, hogy ha nem adod meg a kötelező adatokat, akkor automatikusan ki lesznek töltve egy alapértelmezettel."
+
+msgid "User"
+msgstr "Felhasználó"
+
+msgid "Service"
+msgstr "Szolgáltatás"
+
+msgid "Service name"
+msgstr "Szolgáltatás neve"
+
+msgid "Service description"
+msgstr "Szolgáltatás leírása"
+
+msgid "Connection"
+msgstr "Kapcsolat"
+
+msgid "Lock the host"
+msgstr "Gazda lezárása"
+
+msgid "Anonymous mode"
+msgstr "Névtelen mód"
+
+msgid "Registration allowed"
+msgstr "Regisztráció engedélyezve"
+
+msgid "Use a proxy"
+msgstr "Proxy használata"
+
+msgid "Encryption"
+msgstr "Titkosítás"
+
+msgid "HTTPS storage"
+msgstr "HTTPS tároló"
+
+msgid "Force HTTPS"
+msgstr "HTTPS erőltetése"
+
+msgid "Compression"
+msgstr "Tömörítés"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Ez az oldal segít beállítani, hogy melyik kiszolgálóhoz fog csatlakozni a Jappix.  Így is hagyhatod a beállításokat ha a hivatalos kiszolgálót szeretnéd használni."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Nem tudod mi az a BOSH szerver? Ez egy továbbító a Jappix kliens és az XMPP szerver között, ami a technikai korlátok miatt szükséges."
+
+msgid "Main host"
+msgstr "Fő kiszolgáló"
+
+msgid "Groupchat host"
+msgstr "Csoportos beszélgetés kiszolgálója"
+
+msgid "Anonymous host"
+msgstr "Névtelenségi kiszolgáló"
+
+msgid "Directory host"
+msgstr "Címtár kiszolgáló"
+
+msgid "BOSH host"
+msgstr "BOSH kiszolgáló"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Telepíthetsz néhány extra szoftvert is a szerveredre, hogy kiterjeszd a felhasználói élményt. Néhányat esetleg módosíthatnak a biztonsági korlátozások miatt."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Hogy végrehajtsd ezt hozzá kell férned a szerver héjához és root-ként kell bejelentkezned. Ne felejtsd hogy ez fakultatív, a Jappix működik ezek nélkül a modulok nélkül, de néhány eleme elérhetetlen lehet."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Telepítés után a Jappix ideiglenes állományokat hoz létre. Ez eltarthat egy ideig, addig ne nyomj semmilyen gombra."
+
+msgid "Thanks for using Jappix!"
+msgstr "Köszönjük, hogy a Jappix-ot használtad!"
+
+msgid "Next"
+msgstr "Következő"
+
+msgid "Finish"
+msgstr "Vége"
+
+msgid "Check again"
+msgstr "Ellenőrzés újra"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "A mappa nem írható, Állítsd be a jogosultságokat %s mappán."
+
+msgid "%s is installed on your system."
+msgstr "%s telepítve van a rendszereden."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s nincs telepítve a rendszereden, telepítsd %2s-t."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP maximum feltöltési méret kielégítő (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP maximum feltöltési méret nem kielégítő (%1s), definiáld %2s és %3s közé."
+
+msgid "Jappix manager"
+msgstr "Jappix menedzser"
+
+msgid "Manager access"
+msgstr "Menedzser hozzáférés"
+
+msgid "Statistics"
+msgstr "Statisztikák"
+
+msgid "Hosts"
+msgstr "Kiszolgálók"
+
+msgid "Design"
+msgstr "Formatervezés"
+
+msgid "Repeat"
+msgstr "Ismétlés"
+
+msgid "All"
+msgstr "Minden"
+
+msgid "Horizontal"
+msgstr "Vízszintes"
+
+msgid "Vertical"
+msgstr "Függőleges"
+
+msgid "Center"
+msgstr "Középre"
+
+msgid "Left"
+msgstr "Balra"
+
+msgid "Right"
+msgstr "Jobbra"
+
+msgid "Top"
+msgstr "Fent"
+
+msgid "Bottom"
+msgstr "Lent"
+
+msgid "Adapt"
+msgstr "Adaptálás"
+
+msgid "Color"
+msgstr "Szín"
+
+msgid "Users"
+msgstr "Felhasználók"
+
+msgid "Updates"
+msgstr "Frissítések"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Ez egy korlátozott régió: csak a kijelölt felhasználók tudják menedzselni ezeket a Jappix opciókat."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Kérlek használd az alábbi formát hogy bejelentkezz az adminisztrációs panelre."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "A biztonság érdekében a kapcsolat időben limitált, és ha bezárod a böngésződ, ki leszel jelentkeztetve. "
+
+msgid "Credentials"
+msgstr "Azonosítók"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Sikeresen kijelentkeztél. Viszlát!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Oppá, nem ismertünk fel, mint érvényes adminisztrátort. Nézd meg az azonosítóid!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Jappix feldolgozza az alapvető statisztikákat néhány fontos dologról, lejjebb megtalálod őket."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Változtasd meg a Jappix csomóponti konfigurációit ezzel az eszközzel."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Változtasd meg az XMPP kiszolgálókat a Jappix csomópont szerveren ezzel az eszközzel."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Az összes Jappix csomópont által tárolt fájl menedzselhető ezzel az eszközzel: kérlek válassz ki egy almappát és kezdheted szerkeszteni a tartalmát!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "A Jappix teljesen testre szabható: itt meg tudod változtatni a kinézetét."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Nem érvényes képformátum, kérlek használj PNG, GIF, vagy JPG képet!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "A képet nem tudtuk fogadni, szeretnéd megpróbálni újra?"
+
+msgid "Your image was added to the list!"
+msgstr "A képed hozzá lett adva a listához!"
+
+msgid "Changes saved!"
+msgstr "Változtatások elmentve!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Ehhez a Jappix csomóponthoz több adminisztrátort is tudsz definiálni. Ezzel az eszközzel jelszót is tudsz változtatni."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Frissítsd a Jappix csomópontod ezzel az eszközzel, vagy nézd meg hogy létezik-e egy újabb. Információk fognak megjelenni a legújabb verzióról (angolul)."
+
+msgid "Access statistics"
+msgstr "Elérési statisztikák"
+
+msgid "Share statistics"
+msgstr "Megosztási statisztikák"
+
+msgid "Other statistics"
+msgstr "Egyéb statisztikák"
+
+msgid "January"
+msgstr "Január"
+
+msgid "February"
+msgstr "Február"
+
+msgid "March"
+msgstr "Március"
+
+msgid "April"
+msgstr "Április"
+
+msgid "May"
+msgstr "Május"
+
+msgid "June"
+msgstr "Június"
+
+msgid "July"
+msgstr "Július"
+
+msgid "August"
+msgstr "Augusztus"
+
+msgid "September"
+msgstr "Szeptember"
+
+msgid "October"
+msgstr "Október"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "December"
+
+msgid "Monday"
+msgstr "Hétfő"
+
+msgid "Tuesday"
+msgstr "Kedd"
+
+msgid "Wednesday"
+msgstr "Szerda"
+
+msgid "Thursday"
+msgstr "Csütörtök"
+
+msgid "Friday"
+msgstr "Péntek"
+
+msgid "Saturday"
+msgstr "Szombat"
+
+msgid "Sunday"
+msgstr "Vasárnap"
+
+msgid "Total"
+msgstr "Összeg"
+
+msgid "Cache"
+msgstr "Gyorsítótár"
+
+msgid "Logs"
+msgstr "Logok"
+
+msgid "Music"
+msgstr "Zene"
+
+msgid "Backgrounds"
+msgstr "Hátterek"
+
+msgid "Share"
+msgstr "Megosztás"
+
+msgid "Background"
+msgstr "Háttér"
+
+msgid "Notice"
+msgstr "Megjegyzés"
+
+msgid "Your design preferences have been saved!"
+msgstr "A kinézeti beállításaid elmentettük."
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Kérlek ellenőrizd a bemeneteket: valami hiányzik!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Változtasd meg a Jappix háttered ezzel az eszközzel. Választhatsz ezen kívül egy egyedi színt, vagy feltölthetsz egy képet. Engedd szárnyalni a kreativitásod!"
+
+msgid "Use default background"
+msgstr "Alapértelmezett háttér használata"
+
+msgid "Use your own image"
+msgstr "Használd a saját képed"
+
+msgid "Select a background to use and change the display options."
+msgstr "Háttérkép választása, hogy használd és változtasd a kijelzési opciókat. "
+
+msgid "Use your own color"
+msgstr "Használd a saját színed"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Írd be a hexadecimális kódját annak a színnek, amit háttérként szeretnél használni."
+
+msgid "Manage backgrounds"
+msgstr "Háttérképek menedzselése"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Ezzel az eszközzel hozzá tudsz adni egy új háttérképet a listához. Kérlek küldj egy érvényes képet."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Ha el szeretnél távolítani háttérképeket, használd az alábbi böngészőt."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Definiálj az összes felhasználód számára egy kezdőoldal üzenet, mint a figyelmeztetés, fontos üzenet vagy hirdetés, ezzel az eszközzel. "
+
+msgid "Simple notice"
+msgstr "Egyszerű értesítés"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Ez az értesítés csak egyszerű szöveget tartalmazhat, tehát kódok nem elérhetőek!"
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "HTML, CSS és JavaScript segítségével személyreszabhatod értesítéseidet, de szükséges stíluskódok használata."
+
+msgid "Available updates"
+msgstr "Elérhető frissítések"
+
+msgid "What's new?"
+msgstr "Mi újság?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "A tárolóid nem írhatóak, kérlek használj másikat!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s talán hibát okoz a proxy kapcsolatban, kérlek emeld meg %2s értékét %3s -re!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "A Jappix egy fejlesztői kiadását használod. Frissítsd a tárolónkból ennek a végrehajtásával: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Új Jappix kiadás elérhető! Lesd meg az újdonságokat, és futtasd a frissitőt!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "A te Jappixod elavult. Kattints ide, és frissits a %s verzióra!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Úgy tűnik, hogy jelenlegi verzió a legfrissebb, de ellenőrizheted manuálisan is ide kattintva."
+
+msgid "Check for updates"
+msgstr "Frissítések keresése"
+
+msgid "Update in progress"
+msgstr "Frissítés folyamatban"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix frissitve: nálad jeleneg az utolsó kiadás fut. "
+
+msgid "The update has failed! Please try again later."
+msgstr "Sikertelen frissítés! Próbáld meg később."
+
+msgid "Downloading package..."
+msgstr "Csomagok letöltése..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Az aktuális Jappix rendszer fájlok törlése..."
+
+msgid "Extracting package..."
+msgstr "Csomagok kibontása..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Tároló mappák újra generálása..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix most naprakész!"
+
+msgid "Aborted: socket error!"
+msgstr "Megszakítva: foglaltsági hiba!"
+
+msgid "Aborted: buffer error!"
+msgstr "Megszakítva: puffer hiba!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Megszakítva: nem minden írható!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Megszakítva: nem lehet kicsomagolni a csomagot!"
+
+msgid "Visits"
+msgstr "Látogatottság"
+
+msgid "Daily"
+msgstr "Naponta"
+
+msgid "Weekly"
+msgstr "Hetente"
+
+msgid "Monthly"
+msgstr "Havonta"
+
+msgid "Yearly"
+msgstr "Évente"
+
+msgid "Size"
+msgstr "Méret"
+
+msgid "Clean everything"
+msgstr "Mindent töröl"
+
+msgid "Purge cache"
+msgstr "Cache tisztítása"
+
+msgid "Purge logs"
+msgstr "Logok tisztítása"
+
+msgid "Purge updates"
+msgstr "Frissítések tisztítása"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "A tárolóhely, amit üríteni akarsz üres!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Tartsd frissen a Jappixodat, tisztítsd a tároló mappákat rendszeresen!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Töltsd fel a zenéid (Ogg Vorbis, MP3 vagy WAV formátumban), hogy tudd őket hallgatni a Jappix-ban is!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "A fájl amit felszeretnél tölteni, kisebbnek kell lennie %s-nál/nél."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Maradj összhangban azzal amit a felhasználóid tárolnak a szerveren, és töröld a nem kívánt tartalmakat ezzel az eszközzel."
+
+msgid "Title"
+msgstr "Cím"
+
+msgid "Artist"
+msgstr "Előadó"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Fájl"
+
+msgid "Upload"
+msgstr "Feltöltés"
+
+msgid "The folder is empty."
+msgstr "A mappa üres."
+
+msgid "The music could not be received, please retry!"
+msgstr "A zenét nem tudtuk fogadni, kérlek próbáld újra!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Ez nem egy érvényes zenei fájl formátum, kérlek kódold át Ogg Vorbis, MP3 vagy WAV formátumba!"
+
+msgid "Your music has been added!"
+msgstr "Zene hozzáadva!"
+
+msgid "The selected elements have been removed."
+msgstr "A kiválasztott elemek törölve lettek."
+
+msgid "You must select elements to remove!"
+msgstr "Ahhoz, hogy törölni tudj, ki kell választanod egy elemet!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Adj meg új felhasználót, vagy változtasd meg a jelszót (ehhez adj meg egy létező felhasználó nevet) ezzel az eszközzel. Kérlek válassz egy erős jelszót!"
+
+msgid "Manage"
+msgstr "Intézés"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Felhasználó eltávolítása ezzel az eszközzel. Akkor nem tudsz felhasználót eltávolítani, ha ő maradt az egyetlen."
+
+msgid "The user has been added!"
+msgstr "Felhasználó hozzáadva!"
+
+msgid "The chosen users have been removed."
+msgstr "A kiválaszott felhasználó eltávolítva."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Legalább egy felhasználót ki kell választani ahhoz, hogy törölni lehessen!"
+
+msgid "Yesterday"
+msgstr "Tegnap"
+
+msgid "%s days ago"
+msgstr "%s nappal ezelőtt"
+
+msgid "User currently active"
+msgstr "A felhasználó jelenleg elérhető"
+
+msgid "Last seen: %s"
+msgstr "Utóljára láttad: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inaktív ideje: %s "
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "A barátod úgy tűnik nem kapta meg az üzenete(i)det!"
+
+msgid "Static content server"
+msgstr "Statikus tartalom szerver"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Ez egy statikus tartalom szerver a következőknek: %1a, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Javasolt barátok"
+
+msgid "Check all"
+msgstr "Összeset megjelöl"
+
+msgid "Uncheck all"
+msgstr "Megjelölések visszavonása"
+
+msgid "Choose"
+msgstr "Választás"
+
+msgid "List name"
+msgstr "Nevek listázása"
+
+msgid "Allow"
+msgstr "Elfogad"
+
+msgid "Deny"
+msgstr "Megtagad"
+
+msgid "Group"
+msgstr "Csoport"
+
+msgid "Subscription"
+msgstr "Feliratkozás"
+
+msgid "Both"
+msgstr "Mindkét"
+
+msgid "From"
+msgstr "Feladó"
+
+msgid "Everybody"
+msgstr "Mindenki"
+
+msgid "Send messages"
+msgstr "Üzenetküldés"
+
+msgid "Send queries"
+msgstr "Lekérdezések"
+
+msgid "See my status"
+msgstr "Állapotom"
+
+msgid "Send his/her status"
+msgstr "Az ő státuszának elküldése"
+
+msgid "Everything"
+msgstr "Minden"
+
+msgid "Item"
+msgstr "Elem"
+
+msgid "Order"
+msgstr "Rendez"
+
+msgid "Active for this session"
+msgstr "Aktív erre a szakaszra"
+
+msgid "Always active"
+msgstr "Mindig elérhető"
+
+msgid "User directory"
+msgstr "Felhasználói könyvtár"
+
+msgid "Search a friend"
+msgstr "Egy barát keresése"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "A megkövetelt tulajdonságot a fogadó vagy a szerver nem tudja implementálni, ezért ezért művelet nem hajtható végre."
+
+msgid "This is a repeat from %s"
+msgstr "Ez egy ismétlés %s -től"
+
+msgid "Loading comments..."
+msgstr "Hozzászólások betöltése.."
+
+msgid "Type your comment here..."
+msgstr "Hozzászólok..."
+
+msgid "Could not get the comments!"
+msgstr "A kommentek nem tölthetők be"
+
+msgid "Show comments"
+msgstr "Mutasd a hozzászólásokat"
+
+msgid "Send him/her a message"
+msgstr "Küldj neki üzenetet"
+
+msgid "Start a chat with him/her"
+msgstr "Beszélj vele"
+
+msgid "Media integration"
+msgstr "Média integráció"
+
+msgid "Comments locked!"
+msgstr "Hozzászólás lezárva!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Írj valamit, amit megosztanál a barátaiddal..."
+
+msgid "changed his/her nickname to %s"
+msgstr "megváltoztatta a felhasználónevét %s -re"
+
+msgid "commented an item you follow: “%s”."
+msgstr "Kommentálva egy elem amit követsz: “%s”."
+
+msgid "Hide"
+msgstr "Elrejt"
+
+msgid "liked your post: “%s”."
+msgstr "kedveli a bejegyzésedet: “%s”"
+
+msgid "quoted you somewhere: “%s”."
+msgstr "szavaztak rád valahol: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "írt a faladra: “%s”"
+
+msgid "tagged you in a photo (%s)."
+msgstr "megjelöltek egy képen (%s). "
+
+msgid "tagged you in a video (%s)."
+msgstr "megjelöltek egy videón (%s). "
+
+msgid "Show"
+msgstr "Mutat"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Szükséged van segítségre? A legjobb, ha elolvasod a dokumentációnkat arról, hogyan töltsd ki az űrlapot!"
+
+msgid "Pubsub host"
+msgstr "Pubsub kiszolgáló"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "A Jappix egy nagyszerű közösségi felület, amit bárhonnan és bármikor elérhetsz, és bárkivel beszélhetsz."
+
+msgid "Manager link"
+msgstr "Menedzser link"
+
+msgid "User uploads server"
+msgstr "Felhasználói feltöltések szervere"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Ez a következők felhasználói feltöltések szervere: %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Be tudod állítani a saját vízjeled az alapértelmezett helyett. Légy óvatos a méretével és a színével kapcsolatban!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Minden logó föltöltése egy ajánlott maximum mérettel."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Nem megfelelő képformátum, kérlek PNG-t használj!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "A vízjeled sikeresen módosítva!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "A logo formátumodnak PNG-nek kell lennie. Hagyj egy mezőt üresen, és a logo nem lesz megváltoztatva."
+
+msgid "Remove this logo"
+msgstr "Logo eltávolítása"
+
+msgid "View this logo"
+msgstr "Logo megtekintése"
+
+msgid "Send a file"
+msgstr "Fájl küldése"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Amint feltöltötted, a barátaid azonnal le fogják tudni tölteni."
+
+msgid "Groupchats to join"
+msgstr "Csoportos beszélgetéshez csatlakozás"
+
+msgid "Purge sent files"
+msgstr "Elküldött fájlok törlése"
+
+msgid "would like to send you a file: “%s”."
+msgstr "szeretne neked küldeni egy fálj-t : “%s”"
+
+msgid "has accepted to received your file: “%s”."
+msgstr "elfogadta, hogy küldj neki egy fálj-t : “%s”"
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "elutasította a fájl-t: “%s”"
+
+msgid "could not receive your file: “%s”."
+msgstr "nem tudta fogadni a fájl-t: “%s”"
+
+msgid "has received a file exchange request: “%s”."
+msgstr "kapott egy felkérést az alábbi fájl fogadására: “%s”"
+
+msgid "Available shortcuts:"
+msgstr "Elérhető parancsikonok:"
+
+msgid "%s removes the chat logs"
+msgstr "%s eltávolította a beszélgetés előzményeit"
+
+msgid "%s joins a groupchat"
+msgstr "%s csatlakozott a csoportos beszélgetésbe"
+
+msgid "%s closes the chat"
+msgstr "%s bezárta a beszélgetést"
+
+msgid "%s shows the user profile"
+msgstr "%s megmutatta a felhasználói profilját"
+
+msgid "%s sends a message to the room"
+msgstr "%s üzenetet küldött a szobábs"
+
+msgid "%s changes your nickname"
+msgstr "%s megváltoztatta a felhasználói nevedet"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s üzenetet küldött valakinek a szobában"
+
+msgid "%s changes the room topic"
+msgstr "%s megváltoztatta a szoba témáját"
+
+msgid "%s kicks an user of the room"
+msgstr "%s kidobta az egyik felhasználót a szobából"
+
+msgid "%s bans an user of the room"
+msgstr "%s kitiltotta az egyik felhasználót a szobából"
+
+msgid "%s invites someone to join the room"
+msgstr "%s meghívott valakit a szobába"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/id/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/id/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..739a38a
Binary files /dev/null and b/jappixmini/jappix/lang/id/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/id/LC_MESSAGES/main.po b/jappixmini/jappix/lang/id/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..5c7f5ae
--- /dev/null
@@ -0,0 +1,1870 @@
+# Indonesia translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript telah hilang di browser web anda, sehingga anda tidak akan dapat membuka Jappix! Harap perbaiki hal ini."
+
+msgid "An open social network"
+msgstr "Sebuah jaringan sosial terbuka"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Saat ini Jappix sedang mengalami gangguan jaringan, bug atau login yang salah (periksa lagi data kredensial yang telah anda masukkan), maaf untuk ketidaknyamanan ini."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Daftar elemen pada server ini tidak dapat diperoleh!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Kata sandi anda telah dirubah, sekarang anda dapat terhubung ke akun anda dengan data login yang baru."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Akun XMPP anda telah dihapus, selamat tinggal!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Anda telah keluar dari akun XMPP anda, semoga hari anda menyenangkan!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Room yang anda masuki tampaknya tidak tersedia, anda harus membuatnya!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "GroupChat telah dihapus, sekarang orang lain akan dapat membuatnya kembali."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Pengguna yang ingin anda hubungi sedang tidak hadir dalam room."
+
+msgid "Please enter the group chat address to join."
+msgstr "Silahkan masukkan alamat GroupChat untuk bergabung."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Silakan masukkan nama panggilan anda untuk bergabung %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Room ini (%s) dilindungi dengan sebuah kata sandi."
+
+msgid "Your browser is out of date!"
+msgstr "Browser anda telah ketinggalan jaman!"
+
+msgid "Last %s version is better!"
+msgstr "Versi %s terakhir lebih baik!"
+
+msgid "Login"
+msgstr "Masuk"
+
+msgid "Register"
+msgstr "Daftar"
+
+msgid "Here we go!"
+msgstr "Kita mulai!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Kata Sandi"
+
+msgid "Remember me"
+msgstr "Ingat saya"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Alat ini telah dinonaktifkan, anda tidak dapat menggunakannya!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Karena masalah jaringan, anda terputus. Apa yang anda ingin lakukan sekarang?"
+
+msgid "Reconnect"
+msgstr "Hubungkan kembali"
+
+msgid "Messages"
+msgstr "Pesan"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Pilihan"
+
+msgid "Disconnect"
+msgstr "Memutuskan"
+
+msgid "Filter"
+msgstr "Filter"
+
+msgid "Add a friend"
+msgstr "Tambahkan teman"
+
+msgid "Your groupchats"
+msgstr "Groupchats anda"
+
+msgid "Manage your favorite groupchats"
+msgstr "Kelola groupchats favorit anda"
+
+msgid "More stuff"
+msgstr "Kemampuan lain"
+
+msgid "Show all friends"
+msgstr "Tampilkan semua teman"
+
+msgid "Only show connected friends"
+msgstr "Hanya tampilkan teman-teman yang terhubung"
+
+msgid "Message archives"
+msgstr "Arsip pesan"
+
+msgid "Date"
+msgstr "Tanggal"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Silahkan pilih seorang teman untuk melihat riwayat chatting."
+
+msgid "Nothing found for: %s"
+msgstr "Tidak ada hasil untuk: %s"
+
+msgid "A short message?"
+msgstr "Sebuah pesan singkat?"
+
+msgid "How are you?"
+msgstr "Bagaimana kabar anda?"
+
+msgid "What are you doing?"
+msgstr "Apa yang anda lakukan?"
+
+msgid "Join a chat"
+msgstr "Ikut obrolan"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "Available"
+msgstr "Tersedia"
+
+msgid "Talkative"
+msgstr "Latah"
+
+msgid "Away"
+msgstr "Pergi"
+
+msgid "Not available"
+msgstr "Tidak tersedia"
+
+msgid "Busy"
+msgstr "Sibuk"
+
+msgid "Mood"
+msgstr "Suasana hati"
+
+msgid "None"
+msgstr "Tidak ada"
+
+msgid "Crazy"
+msgstr "Gila"
+
+msgid "Excited"
+msgstr "Gembira"
+
+msgid "Playful"
+msgstr "Playful"
+
+msgid "Happy"
+msgstr "Senang"
+
+msgid "Shocked"
+msgstr "Kaget"
+
+msgid "Hot"
+msgstr "Panas"
+
+msgid "Sad"
+msgstr "Sedih"
+
+msgid "Amorous"
+msgstr "Tunjukkan Cinta Kasih"
+
+msgid "Confident"
+msgstr "Yakin"
+
+msgid "Activity"
+msgstr "Aktivitas"
+
+msgid "Chores"
+msgstr "Tugas"
+
+msgid "Drinking"
+msgstr "Minum"
+
+msgid "Eating"
+msgstr "Makan"
+
+msgid "Exercising"
+msgstr "Berolahraga"
+
+msgid "Grooming"
+msgstr "Dandan"
+
+msgid "Appointment"
+msgstr "Janji"
+
+msgid "Inactive"
+msgstr "Tidak aktif"
+
+msgid "Relaxing"
+msgstr "Bersantai"
+
+msgid "Talking"
+msgstr "Berbicara"
+
+msgid "Traveling"
+msgstr "Perjalanan"
+
+msgid "Working"
+msgstr "Bekerja"
+
+msgid "View profile"
+msgstr "Lihat profil"
+
+msgid "Repeat this notice"
+msgstr "Ulangi pemberitahuan ini"
+
+msgid "Remove this notice"
+msgstr "Hapus pemberitahuan ini"
+
+msgid "Your profile"
+msgstr "Profil anda"
+
+msgid "Identity"
+msgstr "Identitas"
+
+msgid "Profile image"
+msgstr "Gambar profil"
+
+msgid "Others"
+msgstr "Lainnya"
+
+msgid "Personal"
+msgstr "Pribadi"
+
+msgid "Complete name"
+msgstr "Nama lengkap"
+
+msgid "Nickname"
+msgstr "Julukan"
+
+msgid "First name"
+msgstr "Nama awalan"
+
+msgid "Last name"
+msgstr "Nama akhiran"
+
+msgid "Date of birth"
+msgstr "Tanggal lahir"
+
+msgid "Contact"
+msgstr "Kontak"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telepon"
+
+msgid "Website"
+msgstr "Situs"
+
+msgid "Current"
+msgstr "Saat ini"
+
+msgid "Delete"
+msgstr "Hapus"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Sayang sekali! anda tidak memiliki gambar profil untuk mendefinisikan anda di dalam kartu identitas!"
+
+msgid "Address"
+msgstr "Alamat"
+
+msgid "Street"
+msgstr "Jalan"
+
+msgid "City"
+msgstr "Kota"
+
+msgid "Postal code"
+msgstr "Kode pos"
+
+msgid "Country"
+msgstr "Negara"
+
+msgid "Biography"
+msgstr "Biografi"
+
+msgid "Important notice"
+msgstr "Pemberitahuan penting"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Hati-hati dengan informasi yang anda tulis ke profil anda, karena bisa diakses oleh setiap orang (bahkan seseorang yang anda tidak inginkan)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Tidak semuanya pribadi di XMPP; ini adalah salah satunya, profil publik anda (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Sangat dianjurkan untuk meng-upload gambar profil (maksimum %s), seperti gambar diri, karena itu yang membuat anda mudah dikenali oleh teman-teman anda."
+
+msgid "Save"
+msgstr "Simpan"
+
+msgid "Cancel"
+msgstr "Batal"
+
+msgid "Edit options"
+msgstr "Edit pilihan"
+
+msgid "Channel"
+msgstr "Channel"
+
+msgid "Commands"
+msgstr "Perintah"
+
+msgid "Sounds"
+msgstr "Suara"
+
+msgid "Privacy"
+msgstr "Privasi"
+
+msgid "Message archiving"
+msgstr "Pengarsipan pesan"
+
+msgid "Store a history of your chats"
+msgstr "Menyimpan riwayat chatting anda"
+
+msgid "Geolocation"
+msgstr "Geolokasi"
+
+msgid "Empty"
+msgstr "Kosong"
+
+msgid "Empty channel"
+msgstr "Kosongkan channel"
+
+msgid "Persistent"
+msgstr "Gigih"
+
+msgid "Maximum notices"
+msgstr "Pemberitahuan maksimum"
+
+msgid "Account"
+msgstr "Akun"
+
+msgid "Change password"
+msgstr "Ubah password"
+
+msgid "Delete account"
+msgstr "Hapus akun"
+
+msgid "Old"
+msgstr "Tua"
+
+msgid "New (2 times)"
+msgstr "Baru (2 kali)"
+
+msgid "Continue"
+msgstr "Lanjutkan"
+
+msgid "To"
+msgstr "Ke"
+
+msgid "Close"
+msgstr "Tutup"
+
+msgid "unknown"
+msgstr "Tidak diketahui"
+
+msgid "Unavailable"
+msgstr "Tidak ditempat"
+
+msgid "is now"
+msgstr "sedang"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Harap tunggu sementara avatar anda sedang di proses ..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Ini dia! Sebuah foto profil baru yang indah!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "File gambar tidak didukung atau memiliki ukuran yang buruk."
+
+msgid "Reply"
+msgstr "Balas"
+
+msgid "Error"
+msgstr "Kesalahan"
+
+msgid "Click here to solve the error"
+msgstr "Klik di sini untuk memperbaiki kesalahan"
+
+msgid "You"
+msgstr "Anda"
+
+msgid "Remove"
+msgstr "Hapus"
+
+msgid "Rename"
+msgstr "Ubah nama"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Hi, saya %s, saya ingin menambahkan anda sebagai teman saya."
+
+msgid "Smiley insertion"
+msgstr "Masukkan Smiley"
+
+msgid "Change style"
+msgstr "Mengubah gaya"
+
+msgid "Text in bold"
+msgstr "Teks dalam huruf tebal"
+
+msgid "Text in italic"
+msgstr "Teks dengan huruf miring"
+
+msgid "Underlined text"
+msgstr "Garisbawahi teks"
+
+msgid "Save chat"
+msgstr "Simpan pembicaraan"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Klik pada link berikut untuk mendapatkan log pembicaraan, tunggu. Lalu klik lagi untuk mendapatkan file."
+
+msgid "This chat is empty!"
+msgstr "Obrolan ini kosong!"
+
+msgid "Generate file!"
+msgstr "Menghasilkan file!"
+
+msgid "Download file!"
+msgstr "Download file!"
+
+msgid "Clean current chat"
+msgstr "Bersihkan obrolan saat ini"
+
+msgid "View chat history"
+msgstr "Lihat riwayat obrolan"
+
+msgid "Show user profile"
+msgstr "Tampilkan profil pengguna"
+
+msgid "Add this contact to your friends"
+msgstr "Tambahkan kontak ini ke teman anda"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Tambahkan groupchat ini ke favorit anda"
+
+msgid "All tabs"
+msgstr "Semua tab"
+
+msgid "Close this tab"
+msgstr "Tutup tab ini"
+
+msgid "no subject defined for this room."
+msgstr "tidak ada subjek yang ditetapkan untuk room ini."
+
+msgid "Administration panel for this room"
+msgstr "Administrasi panel untuk room ini"
+
+msgid "Moderators"
+msgstr "Moderator"
+
+msgid "Participants"
+msgstr "Peserta"
+
+msgid "Visitors"
+msgstr "Pengunjung"
+
+msgid "Manage favorite rooms"
+msgstr "Mengelola room favorit"
+
+msgid "Change favorites"
+msgstr "Ubah favorit"
+
+msgid "Search a room"
+msgstr "Mencari room chat"
+
+msgid "Select a favorite"
+msgstr "Pilih favorit"
+
+msgid "Getting the name..."
+msgstr "Mendapatkan nama..."
+
+msgid "Gateway"
+msgstr "Gateway"
+
+msgid "Name"
+msgstr "Nama"
+
+msgid "Room"
+msgstr "Room"
+
+msgid "Add"
+msgstr "Tambahkan"
+
+msgid "Edit"
+msgstr "Mengedit"
+
+msgid "Search a room on"
+msgstr "Cari kamar di"
+
+msgid "No room found on this server."
+msgstr "Tidak ditemukan room di server ini."
+
+msgid "Service discovery"
+msgstr "Penemuan layanan"
+
+msgid "Server to query"
+msgstr "Server untuk permintaan"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Maaf, tapi entitas tidak mengembalikan hasil apapun!"
+
+msgid "Accounts"
+msgstr "Akun"
+
+msgid "Authentications"
+msgstr "Otentikasi"
+
+msgid "Automation"
+msgstr "Otomatisasi"
+
+msgid "Clients"
+msgstr "Klien"
+
+msgid "Collaboration"
+msgstr "Kolaborasi"
+
+msgid "Components"
+msgstr "Komponen"
+
+msgid "Rooms"
+msgstr "Kamar"
+
+msgid "Directories"
+msgstr "Direktori"
+
+msgid "Gateways"
+msgstr "Gateway"
+
+msgid "News"
+msgstr "Berita"
+
+msgid "Hierarchy"
+msgstr "Hirarki"
+
+msgid "Proxies"
+msgstr "Proxy"
+
+msgid "Publication/Subscription"
+msgstr "Publikasi / Berlangganan"
+
+msgid "Storage"
+msgstr "Penyimpanan"
+
+msgid "Service offline or broken"
+msgstr "Layanan sedang offline atau rusak"
+
+msgid "Your inbox"
+msgstr "Kotak masuk anda"
+
+msgid "Available actions"
+msgstr "Tersedia tindakan"
+
+msgid "Clean"
+msgstr "Bersih"
+
+msgid "New"
+msgstr "Baru"
+
+msgid "Received"
+msgstr "Diterima"
+
+msgid "Subject"
+msgstr "Subjek"
+
+msgid "Content"
+msgstr "Konten"
+
+msgid "Send message"
+msgstr "Kirim pesan"
+
+msgid "Your inbox is empty."
+msgstr "Kotak masuk kosong."
+
+msgid "MUC administration"
+msgstr "MUC administrasi"
+
+msgid "You administrate this room"
+msgstr "Anda administrate room ini"
+
+msgid "Enter new subject"
+msgstr "Masukkan subjek baru"
+
+msgid "Configuration"
+msgstr "Konfigurasi"
+
+msgid "Authorizations"
+msgstr "Otorisasi"
+
+msgid "Member list"
+msgstr "Daftar anggota"
+
+msgid "Owner list"
+msgstr "Daftar pemilik"
+
+msgid "Administrator list"
+msgstr "Daftar Administrator"
+
+msgid "Outcast list"
+msgstr "Daftar terbuang"
+
+msgid "Add an input"
+msgstr "Tambahkan masukan"
+
+msgid "Destroy this MUC"
+msgstr "Hancurkan MUC ini"
+
+msgid "Yes, let's do it!"
+msgstr "Ya, mari kita melakukannya!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Teman anda sedang memperhatikan percakapan."
+
+msgid "Your friend is writing a message..."
+msgstr "Teman anda sedang menulis pesan ..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Teman anda berhenti menulis pesan."
+
+msgid "Your friend is doing something else."
+msgstr "Teman anda sedang melakukan sesuatu yang lain."
+
+msgid "Your friend closed the chat."
+msgstr "Teman anda menutup obrolan."
+
+msgid "Requesting this service..."
+msgstr "Meminta layanan ini ..."
+
+msgid "Loading"
+msgstr "Pemuatan"
+
+msgid "joined the chat room"
+msgstr "bergabung dengan chat room"
+
+msgid "left the chat room"
+msgstr "meninggalkan chat room"
+
+msgid "no status"
+msgstr "tidak ada status"
+
+msgid "has been kicked"
+msgstr "telah ditendang"
+
+msgid "has been banned"
+msgstr "telah dilarang"
+
+msgid "no reason"
+msgstr "tanpa alasan"
+
+msgid "Communicate with the entire world!"
+msgstr "Berkomunikasi dengan seluruh dunia!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Hal ini memungkinkan anda untuk berhubungan dengan jutaan pengguna yang saat ini menggunakan jaringan XMPP seperti yang anda lakukan dengan Jappix. Bergabung dengan komunitas dan tetap bebas!"
+
+msgid "Hi there!"
+msgstr "Halo semua!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Selamat datang di %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Masuk ke akun XMPP anda atau buat yang baru dengan gratis!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix adalah sebuah proyek open source dari PostPro, sebuah organisasi non-profit yang memberikan kita bantuan besar."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Masuk ke akun XMPP anda. Anda juga dapat menggunakan %s untuk bergabung dengan suatu groupchat."
+
+msgid "Previous"
+msgstr "Sebelumnya"
+
+msgid "General"
+msgstr "Umum"
+
+msgid "Advanced"
+msgstr "Lebih lanjut"
+
+msgid "Resource"
+msgstr "Sumber daya"
+
+msgid "Priority"
+msgstr "Prioritas"
+
+msgid "Low"
+msgstr "Rendah"
+
+msgid "Medium"
+msgstr "Menengah"
+
+msgid "High"
+msgstr "Tinggi"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Masukkan groupchat yang anda ingin bergabung dan nick yang ingin anda miliki. Anda juga dapat kembali ke %s."
+
+msgid "login page"
+msgstr "halaman masuk"
+
+msgid "Share this link with your friends:"
+msgstr "Berbagi link ini dengan teman anda:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Daftarkan akun XMPP baru untuk bergabung dengan teman-teman anda di atas awan sosial anda sendiri. Sederhana bukan!"
+
+msgid "Required"
+msgstr "Diperlukan"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Anda telah terdaftar, alamat XMPP anda adalah:"
+
+msgid "Manager"
+msgstr "Manajer"
+
+msgid "Project"
+msgstr "Proyek"
+
+msgid "Encrypted"
+msgstr "Terenkripsi"
+
+msgid "Unencrypted"
+msgstr "Tidak terenkripsi"
+
+msgid "Where are you?"
+msgstr "Di mana anda?"
+
+msgid "What's up with you?"
+msgstr "Ada apa dengan anda?"
+
+msgid "Fetching the social channel..."
+msgstr "Mengambil saluran sosial ..."
+
+msgid "You are synchronized with your network."
+msgstr "Anda telah disinkronkan dengan jaringan anda."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Tidak dapat mengirim apapun: anda hanya dapat menerima pemberitahuan!"
+
+msgid "Media viewer"
+msgstr "Media penampil"
+
+msgid "Browse"
+msgstr "Daftar"
+
+msgid "Command"
+msgstr "Perintah"
+
+msgid "Subscribe"
+msgstr "Berlangganan"
+
+msgid "Join"
+msgstr "Bergabung"
+
+msgid "Automatic"
+msgstr "Otomatis"
+
+msgid "Search"
+msgstr "Pencarian"
+
+msgid "No result!"
+msgstr "Tidak ada hasil!"
+
+msgid "No notifications."
+msgstr "Tidak ada pemberitahuan."
+
+msgid "would like to add you as a friend."
+msgstr "ingin menambahkan anda sebagai teman."
+
+msgid "would like you to join this chatroom:"
+msgstr "ingin anda untuk bergabung dengan chatroom:"
+
+msgid "Do you accept?"
+msgstr "Apakah anda menerima?"
+
+msgid "Yes"
+msgstr "Ya"
+
+msgid "No"
+msgstr "Tidak"
+
+msgid "would like to get authorization."
+msgstr "ingin mendapatkan otorisasi."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Apakah anda ingin melihat teman-teman %s yang menyarankan anda?"
+
+msgid "Submit"
+msgstr "Menyerahkan"
+
+msgid "Client"
+msgstr "Klien"
+
+msgid "System"
+msgstr "Sistem"
+
+msgid "Local time"
+msgstr "Waktu setempat"
+
+msgid "Comments"
+msgstr "Komentar"
+
+msgid "User profile"
+msgstr "Profil pengguna"
+
+msgid "See his/her position on the globe"
+msgstr "Lihat / nya posisinya di dunia"
+
+msgid "Confirm"
+msgstr "Menegaskan"
+
+msgid "anonymous mode"
+msgstr "modus anonim"
+
+msgid "Groups"
+msgstr "Grup"
+
+msgid "Unclassified"
+msgstr "Unclassified"
+
+msgid "Authorize"
+msgstr "Otorisasi"
+
+msgid "Ask for authorization"
+msgstr "Minta untuk otorisasi"
+
+msgid "Unblock"
+msgstr "Tidak dilarang"
+
+msgid "Prohibit"
+msgstr "Melarang"
+
+msgid "Block"
+msgstr "Dilarang"
+
+msgid "Chat"
+msgstr "Bicara"
+
+msgid "Groupchat"
+msgstr "Groupchat"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Handphone"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Ponsel"
+
+msgid "Please wait..."
+msgstr "Silakan tunggu ..."
+
+msgid "Please enable JavaScript"
+msgstr "Silahkan mengaktifkan JavaScript"
+
+msgid "Your channel"
+msgstr "Saluran anda"
+
+msgid "Channel of"
+msgstr "Saluran dari "
+
+msgid "More notices..."
+msgstr "Pemberitahuan yang lain..."
+
+msgid "Attach a file"
+msgstr "Lampirkan file"
+
+msgid "Send"
+msgstr "Kirim"
+
+msgid "Unattach the file"
+msgstr "Unattach file"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Sebuah kesalahan terjadi ketika mengupload file anda: mungkin itu terlalu besar (maksimum %s) atau dilarang!"
+
+msgid "Authorization failed"
+msgstr "Otorisasi gagal"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Pendaftaran gagal, silakan pilih username yang berbeda"
+
+msgid "Service unavailable"
+msgstr "Layanan tidak tersedia"
+
+msgid "Internal server error, try later"
+msgstr "Server error, coba beberapa saat kemudian"
+
+msgid "Your form has been sent."
+msgstr "Formulir anda telah dikirim."
+
+msgid "Application"
+msgstr "Aplikasi"
+
+msgid "XMPP links"
+msgstr "XMPP link"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Buka XMPP link dengan Jappix"
+
+msgid "changed the subject to:"
+msgstr "mengubah topik menjadi:"
+
+msgid "Welcome!"
+msgstr "Selamat Datang!"
+
+msgid "Friends"
+msgstr "Teman"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Selamat datang di Jappix, awan sosial anda sendiri!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Sebelum anda mulai menggunakannya, anda harus mengubah beberapa pengaturan, mencari teman dan melengkapi profil anda."
+
+msgid "Enable notification sounds"
+msgstr "Aktifkan suara pemberitahuan"
+
+msgid "Share your position on the globe"
+msgstr "Berbagi posisi anda di dunia"
+
+msgid "Offline friends"
+msgstr "Teman offline"
+
+msgid "Don't hide offline friends"
+msgstr "Jangan sembunyikan teman offline"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Gunakan tool ini untuk menemukan teman-teman anda pada server yang anda gunakan sekarang, atau menambahkan mereka nanti."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Usaha hebat! Sekarang, anda dapat memberitahukan Jappix ke teman-teman anda!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Ketika anda akan menekan tombol simpan, editor profil akan dibuka. Selamat bersosialisasi!"
+
+msgid "Share Jappix on %s"
+msgstr "Berbagi Jappix ke %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Menggunakan Jappix, sebuah platform sosial yang terbuka. Saya s!%"
+
+msgid "Unknown name"
+msgstr "Nama tidak diketahui"
+
+msgid "Unknown country"
+msgstr "Negara tidak diketahui"
+
+msgid "Click to enable"
+msgstr "Klik untuk mengaktifkan"
+
+msgid "Click to disable"
+msgstr "Klik untuk menonaktifkan"
+
+msgid "Installation"
+msgstr "Instalasi"
+
+msgid "Jappix installation"
+msgstr "Instalasi Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Selamat datang di instalasi Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Alat ini akan membantu anda secara cepat menginstal Jappix, fitur berbasis XMPP penuh pertama untuk platform sosial, pada server anda. Anda bahkan tidak perlu pengetahuan teknis apapun."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Mari kita lihat langkah-langkah instalasi:"
+
+msgid "Welcome"
+msgstr "Selamat Datang di"
+
+msgid "Storage configuration"
+msgstr "Konfigurasi penyimpanan"
+
+msgid "Administrator account"
+msgstr "Akun administrator"
+
+msgid "Main configuration"
+msgstr "Konfigurasi utama"
+
+msgid "Hosts configuration"
+msgstr "Host konfigurasi"
+
+msgid "Services installation"
+msgstr "Instalasi layanan"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Jika bahasa saat ini tidak cocok dengan anda (%1s), anda dapat membuat Jappix berbicara %2s itu akan disimpan."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Jika anda ingin mendapatkan beberapa bantuan tentang instalasi dan konfigurasi Jappix, anda dapat menggunakan seluruh dokumentasi kami, tersedia di:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Saatnya untuk membangun 'sosial cloud' anda sendiri: slahkan pergi ke langkah berikutnya!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix menyimpan data persisten (seperti shared file, log chatting, musik anda sendiri dan konfigurasi nya) ke dalam folder penyimpanan tunggal yang aman."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix harus mampu menulis dalam folder ini untuk membuat sub-direktori. Jika tidak, anda harus mengatur hak untuk %1s atau mengubah pemilik folder untuk %2s (tergantung dari konfigurasi anda)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Folder dapat ditulis, anda dapat melanjutkan!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix menawarkan kemungkinan untuk mengelola konfigurasi anda, menginstal plugin baru atau mencari update. Itulah mengapa anda harus membuat account administrator untuk mengakses manajer."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Ketika Jappix akan diinstal, cukup klik pada link manajer di halaman rumah untuk mengaksesnya."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Ups, anda melewatkan sesuatu atau dua kata sandi tidak cocok!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix membutuhkan beberapa nilai yang spesifik untuk bekerja. Harap perbaiki masukan sebagai berikut (atau menyimpan nilai-nilai default, yang cukup untuk kebanyakan orang)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Catatan, jika anda tidak menentukan nilai yang bersifat wajib, maka akan secara otomatis dilengkapi dengan default."
+
+msgid "User"
+msgstr "Pengguna"
+
+msgid "Service"
+msgstr "Layanan"
+
+msgid "Service name"
+msgstr "Nama layanan"
+
+msgid "Service description"
+msgstr "Layanan deskripsi"
+
+msgid "Connection"
+msgstr "Koneksi"
+
+msgid "Lock the host"
+msgstr "Kunci host"
+
+msgid "Anonymous mode"
+msgstr "Modus anonim"
+
+msgid "Registration allowed"
+msgstr "Pendaftaran diperbolehkan"
+
+msgid "Use a proxy"
+msgstr "Gunakan proxy"
+
+msgid "Encryption"
+msgstr "Enkripsi"
+
+msgid "HTTPS storage"
+msgstr "Penyimpanan HTTPS"
+
+msgid "Force HTTPS"
+msgstr "memaksa HTTPS"
+
+msgid "Compression"
+msgstr "Kompresi"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Halaman ini membantu anda menentukan default host Jappix yang akan terhubung. Anda dapat meninggalkan seperti yang sudah ada dan melanjutkan jika anda ingin menggunakan host layanan resmi."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Mungkin anda tidak tahu apa server Bosh adalah? Pada kenyataannya, ini adalah sebuah relay antara klien dan server Jappix XMPP, yang diperlukan karena keterbatasan teknis."
+
+msgid "Main host"
+msgstr "Host Utama"
+
+msgid "Groupchat host"
+msgstr "Host Groupchat"
+
+msgid "Anonymous host"
+msgstr "Host Anonim"
+
+msgid "Directory host"
+msgstr "Host Direktori"
+
+msgid "BOSH host"
+msgstr "Host Bosh"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Anda dapat menginstal beberapa software tambahan pada server anda, untuk memperpanjang fitur Jappix anda. Beberapa yang lain mungkin diubah, karena pembatasan keamanan yang ditetapkan secara default."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Untuk melakukan ini, anda harus dapat akses shell server anda dan login sebagai root. Ingat ini adalah fakultatif, Jappix akan bekerja tanpa modul ini, tetapi beberapa dari fitur-fiturnya akan tersedia."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Setelah anda selesai setup, Jappix akan menghasilkan file cache. Mungkin lambat, hanya menunggu sampai aplikasi ditampilkan dan tidak menekan tombol apapun."
+
+msgid "Thanks for using Jappix!"
+msgstr "Terima kasih untuk menggunakan Jappix!"
+
+msgid "Next"
+msgstr "Berikutnya"
+
+msgid "Finish"
+msgstr "Selesai"
+
+msgid "Check again"
+msgstr "Periksa lagi"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Folder tidak dapat ditulis, mengatur hak akses yang benar ke direktori %s."
+
+msgid "%s is installed on your system."
+msgstr "%s diinstal pada sistem anda."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s tidak diinstal pada sistem anda, anda harus menginstal %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP ukuran maksimum upload cukup (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP ukuran maksimum upload tidak cukup (%1s), anda harus mendefinisikan ke %2s di %3s."
+
+msgid "Jappix manager"
+msgstr "Jappix manajer"
+
+msgid "Manager access"
+msgstr "Manajer akses"
+
+msgid "Statistics"
+msgstr "Statistik"
+
+msgid "Hosts"
+msgstr "Host"
+
+msgid "Design"
+msgstr "Desain"
+
+msgid "Repeat"
+msgstr "Ulangi"
+
+msgid "All"
+msgstr "Semua"
+
+msgid "Horizontal"
+msgstr "Horisontal"
+
+msgid "Vertical"
+msgstr "Vertikal"
+
+msgid "Center"
+msgstr "Pusat"
+
+msgid "Left"
+msgstr "Kiri"
+
+msgid "Right"
+msgstr "Kanan"
+
+msgid "Top"
+msgstr "Atas"
+
+msgid "Bottom"
+msgstr "Bawah"
+
+msgid "Adapt"
+msgstr "Menyesuaikan"
+
+msgid "Color"
+msgstr "Warna"
+
+msgid "Users"
+msgstr "Pengguna"
+
+msgid "Updates"
+msgstr "Update"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Ini adalah area terbatas: hanya pengguna yang berwenang dapat mengatur node ini Jappix."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Silakan gunakan formulir di bawah untuk login ke panel administrasi."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Untuk meningkatkan keamanan, sesi yang terbatas dalam waktu dan saat browser anda akan ditutup, anda akan log out."
+
+msgid "Credentials"
+msgstr "Surat kepercayaan"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Anda telah keluar. Selamat tinggal!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Ups, anda tidak dapat diakui sebagai administrator yang valid. Periksa kredensial anda!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Statistik dasar yang diproses oleh Jappix tentang beberapa hal penting, anda dapat menemukan mereka di bawah ini."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Ubah Jappix konfigurasi node dengan alat ini."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Mengubah host XMPP bahwa node ini Jappix melayani dengan alat ini."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Semua file ini disimpan Jappix node dapat dikelola dengan alat ini: silahkan pilih sub-folder dan mulai mengedit isinya!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix sepenuhnya dapat disesuaikan: anda bisa mengubah desain di sini."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Ini bukan gambar yang sesuai, tolong gunakan PNG, GIF atau JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Gambar tidak dapat diterima, maukah kau coba lagi?"
+
+msgid "Your image was added to the list!"
+msgstr "Gambar anda telah ditambahkan ke dalam daftar!"
+
+msgid "Changes saved!"
+msgstr "Perubahan disimpan!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Anda dapat menentukan lebih dari satu administrator untuk node ini Jappix. Anda juga dapat mengubah password dengan alat ini."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Perbarui simpul Jappix anda dengan alat ini, atau periksa jika yang baru tersedia. Informasi tentang versi terbaru juga ditampilkan (dalam bahasa Inggris)."
+
+msgid "Access statistics"
+msgstr "Akses statistik"
+
+msgid "Share statistics"
+msgstr "Berbagi statistik"
+
+msgid "Other statistics"
+msgstr "Lain statistik"
+
+msgid "January"
+msgstr "Januari"
+
+msgid "February"
+msgstr "Februari"
+
+msgid "March"
+msgstr "Maret"
+
+msgid "April"
+msgstr "April"
+
+msgid "May"
+msgstr "Mei"
+
+msgid "June"
+msgstr "Juni"
+
+msgid "July"
+msgstr "Juli"
+
+msgid "August"
+msgstr "Agustus"
+
+msgid "September"
+msgstr "September"
+
+msgid "October"
+msgstr "Oktober"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "Desember"
+
+msgid "Monday"
+msgstr "Senin"
+
+msgid "Tuesday"
+msgstr "Selasa"
+
+msgid "Wednesday"
+msgstr "Rabu"
+
+msgid "Thursday"
+msgstr "Kamis"
+
+msgid "Friday"
+msgstr "Jumat"
+
+msgid "Saturday"
+msgstr "Sabtu"
+
+msgid "Sunday"
+msgstr "Minggu"
+
+msgid "Total"
+msgstr "Total"
+
+msgid "Cache"
+msgstr "Penutup"
+
+msgid "Logs"
+msgstr "Log"
+
+msgid "Music"
+msgstr "Musik"
+
+msgid "Backgrounds"
+msgstr "Backgrounds"
+
+msgid "Share"
+msgstr "Berbagi"
+
+msgid "Background"
+msgstr "Latar belakang"
+
+msgid "Notice"
+msgstr "Pemberitahuan"
+
+msgid "Your design preferences have been saved!"
+msgstr "Setting gambar anda telah disimpan!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Silakan periksa masukan anda: sesuatu yang hilang!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Ubah latar belakang simpul Jappix dengan alat ini. Anda juga dapat mengatur warna kustom atau foto yang diunggah. Biarkan kreativitas anda mengalir!"
+
+msgid "Use default background"
+msgstr "Gunakan latar belakang standar"
+
+msgid "Use your own image"
+msgstr "Gunakan gambar anda sendiri"
+
+msgid "Select a background to use and change the display options."
+msgstr "Pilih latar belakang untuk menggunakan dan mengubah pilihan tampilan."
+
+msgid "Use your own color"
+msgstr "Gunakan warna sendiri"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Ketik nilai warna heksadesimal yang ingin anda gunakan sebagai latar belakang."
+
+msgid "Manage backgrounds"
+msgstr "Mengelola latar belakang"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Anda dapat menambahkan latar belakang baru ke dalam daftar dengan alat ini. Silakan kirim gambar yang valid."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Jika anda ingin menghapus beberapa latar belakang, gunakan browser di bawah ini."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Tentukan pemberitahuan homepage untuk semua pengguna anda, seperti memperingatkan, pesan penting atau sebuah iklan dengan alat ini."
+
+msgid "Simple notice"
+msgstr "Pemberitahuan Sederhana"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Pemberitahuan ini hanya perlu teks sederhana yang akan ditampilkan, tetapi kode tidak diperbolehkan!"
+
+msgid "Advanced notice"
+msgstr "Pemberitahuan Lanjutan"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Anda dapat menyesuaikan pemberitahuan anda dengan embedded HTML, CSS dan JavaScript, tetapi anda perlu kode tampilannya."
+
+msgid "Available updates"
+msgstr "Update tersedia"
+
+msgid "What's new?"
+msgstr "Apa yang baru?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Folder penyimpanan anda tidak dapat ditulis, silahkan menerapkan hak-hak baik!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s dapat menyebabkan masalah ke proxy, silahkan peningkatan nilai %2s sampai dengan %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Anda menggunakan versi pengembangan dari Jappix. Pembaruan melalui repositori kita dengan menjalankan: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Sebuah versi Jappix baru tersedia! Memeriksa apa yang baru dan peluncuran update!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Versi anda keluar untuk tanggal. Update sekarang untuk %s dengan mengklik di sini!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Versi anda tampaknya up to date, tetapi anda dapat memeriksa update secara manual dengan mengklik di sini."
+
+msgid "Check for updates"
+msgstr "Periksa pembaruan"
+
+msgid "Update in progress"
+msgstr "Update sedang diproses"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix telah diperbarui: anda sekarang menjalankan versi terbaru. Selamat Bersenang-senang!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Update telah gagal! Silakan coba lagi nanti."
+
+msgid "Downloading package..."
+msgstr "Men-download paket ..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Menghapus file saat ini Jappix sistem ..."
+
+msgid "Extracting package..."
+msgstr "Ekstrak paket ..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Regenerasi penyimpanan folder ..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix sekarang terbaru!"
+
+msgid "Aborted: socket error!"
+msgstr "Dibatalkan: kesalahan socket!"
+
+msgid "Aborted: buffer error!"
+msgstr "Dibatalkan: kesalahan penyangga!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Dibatalkan: semuanya tidak ditulis!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Dibatalkan: tidak bisa ekstrak paket itu!"
+
+msgid "Visits"
+msgstr "Kunjungan"
+
+msgid "Daily"
+msgstr "Harian"
+
+msgid "Weekly"
+msgstr "Mingguan"
+
+msgid "Monthly"
+msgstr "Bulanan"
+
+msgid "Yearly"
+msgstr "Tahunan"
+
+msgid "Size"
+msgstr "Ukuran"
+
+msgid "Clean everything"
+msgstr "Bersihkan semua"
+
+msgid "Purge cache"
+msgstr "Purge Cache"
+
+msgid "Purge logs"
+msgstr "Purge log"
+
+msgid "Purge updates"
+msgstr "Purge update"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Folder penyimpanan yang anda ingin bersihkan sekarang kosong!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Pertahankan Jappix anda agar selalu segar dan cepat, bersihkan folder penyimpanan secara teratur!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Upload musik anda (Ogg Vorbis, MP3 atau WAV) untuk dapat didengarkan di Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "File yang ingin anda upload harus lebih kecil dari %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Tetap setia dalam apa toko pengguna anda pada server anda dan menghapus konten yang tidak diinginkan dengan alat ini."
+
+msgid "Title"
+msgstr "Judul"
+
+msgid "Artist"
+msgstr "Artist"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "File yang"
+
+msgid "Upload"
+msgstr "Upload"
+
+msgid "The folder is empty."
+msgstr "Folder kosong."
+
+msgid "The music could not be received, please retry!"
+msgstr "Musik tidak dapat didengar, silahkan coba lagi"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Ini bukan file musik yang valid, silakan mengkodekan dalam Ogg Vorbis, MP3 atau WAV!"
+
+msgid "Your music has been added!"
+msgstr "Lagu anda telah dimasukkan"
+
+msgid "The selected elements have been removed."
+msgstr "Unsur-unsur yang dipilih telah dihapus."
+
+msgid "You must select elements to remove!"
+msgstr "Anda harus memilih elemen untuk menghapus!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Menambahkan user baru dengan alat ini, atau mengubah password (ketikkan nama pengguna yang sudah ada). Harap kirimkan password yang kuat!"
+
+msgid "Manage"
+msgstr "Mengelola"
+
+msgid "List"
+msgstr "Daftar"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Hapus pengguna dengan alat ini. Perhatikan bahwa anda tidak dapat menghapus pengguna jika ia adalah satu-satunya yang tersisa."
+
+msgid "The user has been added!"
+msgstr "Pengguna telah ditambahkan!"
+
+msgid "The chosen users have been removed."
+msgstr "Para pengguna yang dipilih telah dihapus."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Anda harus memilih satu atau lebih pengguna untuk dihapus"
+
+msgid "Yesterday"
+msgstr "Kemarin"
+
+msgid "%s days ago"
+msgstr "%s hari yang lalu"
+
+msgid "User currently active"
+msgstr "Pengguna yang sedang aktif"
+
+msgid "Last seen: %s"
+msgstr "Terakhir dilihat: %s"
+
+msgid "Inactive since: %s"
+msgstr "Tidak aktif sejak: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Teman anda tampaknya tidak menerima pesan anda (s)!"
+
+msgid "Static content server"
+msgstr "Statis server isi"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Ini adalah server konten statis untuk %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Sarankan teman"
+
+msgid "Check all"
+msgstr "Periksa semua"
+
+msgid "Uncheck all"
+msgstr "Hapus centang semua"
+
+msgid "Choose"
+msgstr "Pilih"
+
+msgid "List name"
+msgstr "Daftar nama"
+
+msgid "Allow"
+msgstr "Perbolehkan"
+
+msgid "Deny"
+msgstr "Menolak"
+
+msgid "Group"
+msgstr "Kelompok"
+
+msgid "Subscription"
+msgstr "Berlangganan"
+
+msgid "Both"
+msgstr "Keduanya"
+
+msgid "From"
+msgstr "Dari"
+
+msgid "Everybody"
+msgstr "Semua orang"
+
+msgid "Send messages"
+msgstr "Kirim pesan"
+
+msgid "Send queries"
+msgstr "Kirim query"
+
+msgid "See my status"
+msgstr "Lihat status saya"
+
+msgid "Send his/her status"
+msgstr "Kirim statusnya"
+
+msgid "Everything"
+msgstr "Segalanya"
+
+msgid "Item"
+msgstr "Barang"
+
+msgid "Order"
+msgstr "Rangka"
+
+msgid "Active for this session"
+msgstr "Aktif untuk sesi ini"
+
+msgid "Always active"
+msgstr "Selalu aktif"
+
+msgid "User directory"
+msgstr "Direktori user"
+
+msgid "Search a friend"
+msgstr "Cari teman"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Fitur yang diminta tidak dilaksanakan oleh penerima atau server dan karena itu tidak dapat diproses."
+
+msgid "This is a repeat from %s"
+msgstr "Ini adalah pengulangan dari %s"
+
+msgid "Loading comments..."
+msgstr "Memuat komentar..."
+
+msgid "Type your comment here..."
+msgstr "Ketik komentar anda di sini..."
+
+msgid "Could not get the comments!"
+msgstr "Tidak dapat menampilkan komentar!"
+
+msgid "Show comments"
+msgstr "Tampilkan komentar"
+
+msgid "Send him/her a message"
+msgstr "Kirim kan dia pesan"
+
+msgid "Start a chat with him/her"
+msgstr "Mulai obrolan dengan dia"
+
+msgid "Media integration"
+msgstr "Integrasi Media"
+
+msgid "Comments locked!"
+msgstr "Komentar terkunci!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Ketik sesuatu untuk dibagikan ke teman..."
+
+msgid "changed his/her nickname to %s"
+msgstr "merubah nama panggilannya ke %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "mengkomentari item yang kamu ikuti: “%s”."
+
+msgid "Hide"
+msgstr "Menyembunyikan"
+
+msgid "liked your post: “%s”."
+msgstr "suka dengan isian anda: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "dikutip di suatu tempat: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "diterbitkan di dinding: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "tag anda di photo (%s)"
+
+msgid "tagged you in a video (%s)."
+msgstr "tag anda di video (%s)."
+
+msgid "Show"
+msgstr "Tampilkan"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Perlu bantuan? Anda sebaiknya membaca halaman dokumentasi kami tentang bagaimana mengisi formulir ini!"
+
+msgid "Pubsub host"
+msgstr "Host Pubsub"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix adalah sebuah platform sosial yang hebat, yang dapat Anda akses di manapun Anda berada, kapan pun Anda inginkan dan berkomunikasi dengan siapapun yang Anda inginkan."
+
+msgid "Manager link"
+msgstr "Link manager"
+
+msgid "User uploads server"
+msgstr "Server upload pengguna"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Ini server upload pengguna untuk %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Anda dapat mengatur logo layanan Anda sendiri untuk menggantikan default. Jaga ukuran dan warna utama logo masing-masing!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Upload masing-masing logo dengan ukuran pixel maksimum yang disarankan."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Ini bukan gambar yang sesuai, tolong gunakan format PNG!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Servis logo anda telah sukses diganti!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Format logo anda harus PNG. Tinggalkan field kosong dan Logo tidak akan terganti."
+
+msgid "Remove this logo"
+msgstr "Hapus logo ini"
+
+msgid "View this logo"
+msgstr "Lihat logo ini"
+
+msgid "Send a file"
+msgstr "Mengirim file"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Setelah upload, teman Anda akan diminta untuk men-download file yang Anda kirim."
+
+msgid "Groupchats to join"
+msgstr "Groupchats untuk bergabung"
+
+msgid "Purge sent files"
+msgstr "Purge file terkirim"
+
+msgid "would like to send you a file: “%s”."
+msgstr "ingin mengirimkan file: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "telah diterima untuk menerima file anda: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "telah menolak untuk menerima file anda: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "tidak bisa menerima file anda: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "telah menerima permintaan pertukaran file: “%s”."
+
+msgid "Available shortcuts:"
+msgstr "Tersedia jalan pintas:"
+
+msgid "%s removes the chat logs"
+msgstr "%s menghapus chat log"
+
+msgid "%s joins a groupchat"
+msgstr "%s bergabung groupchat"
+
+msgid "%s closes the chat"
+msgstr "%s menutup obrolan"
+
+msgid "%s shows the user profile"
+msgstr "%s menunjukkan profil pengguna"
+
+msgid "%s sends a message to the room"
+msgstr "%s mengirim pesan ke room"
+
+msgid "%s changes your nickname"
+msgstr "%s perubahan nama panggilan anda"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s mengirim pesan kepada seseorang di dalam room"
+
+msgid "%s changes the room topic"
+msgstr "%s merubah topik di room"
+
+msgid "%s kicks an user of the room"
+msgstr "%s tendang pengguna room"
+
+msgid "%s bans an user of the room"
+msgstr "%s melarang pengguna ke room"
+
+msgid "%s invites someone to join the room"
+msgstr "%s mengajak seseorang untuk bergabung dalam room"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/it/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/it/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..a5e62f4
Binary files /dev/null and b/jappixmini/jappix/lang/it/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/it/LC_MESSAGES/main.po b/jappixmini/jappix/lang/it/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..092cc8f
--- /dev/null
@@ -0,0 +1,1870 @@
+# Italian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:27+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Javascript è disattivato nel tuo browser, ed è richiesto per lanciare Jappix correttamente!"
+
+msgid "An open social network"
+msgstr "Un network sociale aperto"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix è stato interrotto da un errore di rete, un bug o un login errato (controlla di aver inserito le credenziali corrette), ci spiace per il disagio."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Non sono stato in grado di ottenere la lista elementi di questo server!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "La tua password è stata cambiata, puoi accedere con i tuoi nuovi dati di accesso."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Il tuo account XMPP è stato rimosso, arrivederci!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Ti sei disconnesso dal tuo account XMPP, buona giornata!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "La room a cui hai scelto di partecipare non esiste, dovresti crearla!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "La chat di gruppo è stata rimossa, qualcun altro sarà adesso in grado di ricrearla."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "L'utente che vuoi raggiungere non è presente nella room."
+
+msgid "Please enter the group chat address to join."
+msgstr "Perpiacere inserisci l'indirizzo della chat di gruppo a cui vuoi partecipare."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Perpiacere inserisci il tuo nickname per entrare in %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Questa room (%s) è protetta da una password."
+
+msgid "Your browser is out of date!"
+msgstr "Il tuo browser è obsoleto!"
+
+msgid "Last %s version is better!"
+msgstr "L'ultima versione (%s) è stata migliorata!"
+
+msgid "Login"
+msgstr "Accedi"
+
+msgid "Register"
+msgstr "Registrati"
+
+msgid "Here we go!"
+msgstr "Ecco fatto!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Password"
+
+msgid "Remember me"
+msgstr "Ricordami"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Questo strumento è stato disabilitato, non puoi utilizzarlo!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Per via di un problema di rete, sei stato disconnesso. Cosa vuoi fare adesso?"
+
+msgid "Reconnect"
+msgstr "Riconnetti"
+
+msgid "Messages"
+msgstr "Messaggi"
+
+msgid "Profile"
+msgstr "Profilo"
+
+msgid "Options"
+msgstr "Preferenze"
+
+msgid "Disconnect"
+msgstr "Disconnettiti"
+
+msgid "Filter"
+msgstr "Filtro"
+
+msgid "Add a friend"
+msgstr "Aggiungi un amico o un'amica"
+
+msgid "Your groupchats"
+msgstr "Le tue chat di gruppo"
+
+msgid "Manage your favorite groupchats"
+msgstr "Amministra le tue chat di gruppo preferite"
+
+msgid "More stuff"
+msgstr "Altro"
+
+msgid "Show all friends"
+msgstr "Mostra tutti i tuoi amici"
+
+msgid "Only show connected friends"
+msgstr "Mostra solo gli amici connessi"
+
+msgid "Message archives"
+msgstr "Archivii messaggi"
+
+msgid "Date"
+msgstr "Data"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Selezionare un amico per visualizzare la cronologia della chat"
+
+msgid "Nothing found for: %s"
+msgstr "Nessun risultato per: %s"
+
+msgid "A short message?"
+msgstr "Un piccolo messaggio?"
+
+msgid "How are you?"
+msgstr "Come stai?"
+
+msgid "What are you doing?"
+msgstr "Cosa stai facendo?"
+
+msgid "Join a chat"
+msgstr "Unisciti a una chat"
+
+msgid "Status"
+msgstr "Stato"
+
+msgid "Available"
+msgstr "Disponibile"
+
+msgid "Talkative"
+msgstr "Vuole chiaccherare"
+
+msgid "Away"
+msgstr "Assente"
+
+msgid "Not available"
+msgstr "Indisponibile"
+
+msgid "Busy"
+msgstr "Occupato"
+
+msgid "Mood"
+msgstr "Umore"
+
+msgid "None"
+msgstr "Nessuno"
+
+msgid "Crazy"
+msgstr "Svitato"
+
+msgid "Excited"
+msgstr "Eccitato"
+
+msgid "Playful"
+msgstr "Brioso"
+
+msgid "Happy"
+msgstr "Felice"
+
+msgid "Shocked"
+msgstr "Scioccato"
+
+msgid "Hot"
+msgstr "Ardente"
+
+msgid "Sad"
+msgstr "Triste"
+
+msgid "Amorous"
+msgstr "Amoroso"
+
+msgid "Confident"
+msgstr "Fiducioso"
+
+msgid "Activity"
+msgstr "Attività"
+
+msgid "Chores"
+msgstr "Sta facendo i mestieri..."
+
+msgid "Drinking"
+msgstr "Sta bevendo..."
+
+msgid "Eating"
+msgstr "Sta mangiando..."
+
+msgid "Exercising"
+msgstr "Esercizio"
+
+msgid "Grooming"
+msgstr "Si sta 'spulciando'..."
+
+msgid "Appointment"
+msgstr "Appuntamento"
+
+msgid "Inactive"
+msgstr "Inattivo"
+
+msgid "Relaxing"
+msgstr "Si rilassa"
+
+msgid "Talking"
+msgstr "Discute"
+
+msgid "Traveling"
+msgstr "In viaggio"
+
+msgid "Working"
+msgstr "Lavoro"
+
+msgid "View profile"
+msgstr "Guarda profilo"
+
+msgid "Repeat this notice"
+msgstr "Ripeti questo avviso"
+
+msgid "Remove this notice"
+msgstr "Rimuovi questa nota"
+
+msgid "Your profile"
+msgstr "Il tuo profilo"
+
+msgid "Identity"
+msgstr "Identità"
+
+msgid "Profile image"
+msgstr "Immagine del profilo"
+
+msgid "Others"
+msgstr "Altri"
+
+msgid "Personal"
+msgstr "Personale"
+
+msgid "Complete name"
+msgstr "Nome completo"
+
+msgid "Nickname"
+msgstr "Soprannome"
+
+msgid "First name"
+msgstr "Nome"
+
+msgid "Last name"
+msgstr "Cognome"
+
+msgid "Date of birth"
+msgstr "Data di nascita"
+
+msgid "Contact"
+msgstr "Contattaci"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefono"
+
+msgid "Website"
+msgstr "Sito web"
+
+msgid "Current"
+msgstr "Corrente"
+
+msgid "Delete"
+msgstr "Cancella"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Che peccato, non hai una immagine definita nel profilo della tua vCard!"
+
+msgid "Address"
+msgstr "Indirizzo"
+
+msgid "Street"
+msgstr "Via"
+
+msgid "City"
+msgstr "Città"
+
+msgid "Postal code"
+msgstr "Numero postale"
+
+msgid "Country"
+msgstr "Nazione"
+
+msgid "Biography"
+msgstr "Biografia"
+
+msgid "Important notice"
+msgstr "Avviso importante"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Fai attenzione alle informazione che inserisci nel tuo profilo, perchè potrebbero essere viste da chiunque (anche chi non vuoi)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Non tutto è riservato su XMPP; come il tuo profilo pubblico (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Ti incoraggiamo a caricare un'immagine per il tuo profile (%s massimo), come un'immagine di te stesso/a, ti renderà più facilmente riconoscibile dai tuoi amici."
+
+msgid "Save"
+msgstr "Salva"
+
+msgid "Cancel"
+msgstr "Annullare"
+
+msgid "Edit options"
+msgstr "Modifica opzioni"
+
+msgid "Channel"
+msgstr "Canale"
+
+msgid "Commands"
+msgstr "Comandi"
+
+msgid "Sounds"
+msgstr "Suoni"
+
+msgid "Privacy"
+msgstr "Privacy"
+
+msgid "Message archiving"
+msgstr "Archiviazione messaggi"
+
+msgid "Store a history of your chats"
+msgstr "Salva la cronologia delle tue chats"
+
+msgid "Geolocation"
+msgstr "Geolocazione"
+
+msgid "Empty"
+msgstr "Svuota"
+
+msgid "Empty channel"
+msgstr "Svuota canale"
+
+msgid "Persistent"
+msgstr "Persistente"
+
+msgid "Maximum notices"
+msgstr "Notifica di massimo"
+
+msgid "Account"
+msgstr "Account"
+
+msgid "Change password"
+msgstr "Cambia password"
+
+msgid "Delete account"
+msgstr "Cancella account"
+
+msgid "Old"
+msgstr "Vecchio"
+
+msgid "New (2 times)"
+msgstr "Nuovo (2 volte)"
+
+msgid "Continue"
+msgstr "Continua"
+
+msgid "To"
+msgstr "A"
+
+msgid "Close"
+msgstr "Chiuso"
+
+msgid "unknown"
+msgstr "sconosciuto"
+
+msgid "Unavailable"
+msgstr "Non disponibile"
+
+msgid "is now"
+msgstr "è adesso"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Perpiacere attendi mentre carico il tuo avatar..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Ecco qui, la nuova immagine per il tuo profilo!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Questo file immagine è in un formato non supportato o eccede la dimensione massima."
+
+msgid "Reply"
+msgstr "Rispondere"
+
+msgid "Error"
+msgstr "Errore"
+
+msgid "Click here to solve the error"
+msgstr "Clicca qui per risolvere l'errore"
+
+msgid "You"
+msgstr "Tu"
+
+msgid "Remove"
+msgstr "Rimuovi"
+
+msgid "Rename"
+msgstr "Rinomina"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Ciao, sono %s, vorrei aggiungerti come amico."
+
+msgid "Smiley insertion"
+msgstr "Inserisci un emote"
+
+msgid "Change style"
+msgstr "Cambia stile"
+
+msgid "Text in bold"
+msgstr "Testo in grassetto"
+
+msgid "Text in italic"
+msgstr "Testo in corsivo"
+
+msgid "Underlined text"
+msgstr "Testo sottolineato"
+
+msgid "Save chat"
+msgstr "Salva discussione"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Clicca al link seguente per ottenere il log della chat, aspetta un attimo e clicca un'altra volta per ottenere il file."
+
+msgid "This chat is empty!"
+msgstr "Questa chat è vuota!"
+
+msgid "Generate file!"
+msgstr "Genera il file!"
+
+msgid "Download file!"
+msgstr "Scarica il file!"
+
+msgid "Clean current chat"
+msgstr "Pulisci la discussione corrente"
+
+msgid "View chat history"
+msgstr "Visualizza la cronologia della chat"
+
+msgid "Show user profile"
+msgstr "Mostra il profilo utente"
+
+msgid "Add this contact to your friends"
+msgstr "Aggiungi questo contatto ad i tuoi amici"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Aggiungi questa chat di gruppo ai tuoi favoriti"
+
+msgid "All tabs"
+msgstr "Tutti i cavalieri"
+
+msgid "Close this tab"
+msgstr "Chiudi questo cavaliere"
+
+msgid "no subject defined for this room."
+msgstr "nessun oggetto definito per questa stanza"
+
+msgid "Administration panel for this room"
+msgstr "Pannello di controllo per questa stanza"
+
+msgid "Moderators"
+msgstr "Moderatori"
+
+msgid "Participants"
+msgstr "Partecipanti"
+
+msgid "Visitors"
+msgstr "Visitatori"
+
+msgid "Manage favorite rooms"
+msgstr "Controlla le tue room preferite"
+
+msgid "Change favorites"
+msgstr "Modifica i preferiti"
+
+msgid "Search a room"
+msgstr "Cerca stanza"
+
+msgid "Select a favorite"
+msgstr "Seleziona favorito"
+
+msgid "Getting the name..."
+msgstr "Sto ottenendo il nome..."
+
+msgid "Gateway"
+msgstr "Transporto"
+
+msgid "Name"
+msgstr "Nome"
+
+msgid "Room"
+msgstr "stanza"
+
+msgid "Add"
+msgstr "Aggiungi"
+
+msgid "Edit"
+msgstr "Modifica"
+
+msgid "Search a room on"
+msgstr "Cerca una stanza in"
+
+msgid "No room found on this server."
+msgstr "Nessuna stanza in questo server"
+
+msgid "Service discovery"
+msgstr "Scoperta servizi"
+
+msgid "Server to query"
+msgstr "Server in cui cercare"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Ci dispiace, ma l'entità non ha dato nessun risultato!"
+
+msgid "Accounts"
+msgstr "Accounts"
+
+msgid "Authentications"
+msgstr "Autenticazioni"
+
+msgid "Automation"
+msgstr "Automazione"
+
+msgid "Clients"
+msgstr "Clienti"
+
+msgid "Collaboration"
+msgstr "Collaborazione"
+
+msgid "Components"
+msgstr "Componenti"
+
+msgid "Rooms"
+msgstr "Stanze"
+
+msgid "Directories"
+msgstr "Cartelle"
+
+msgid "Gateways"
+msgstr "Gateways"
+
+msgid "News"
+msgstr "News"
+
+msgid "Hierarchy"
+msgstr "Gerarchia"
+
+msgid "Proxies"
+msgstr "i Proxie"
+
+msgid "Publication/Subscription"
+msgstr "Pubblicazioni/Sottoscrizioni"
+
+msgid "Storage"
+msgstr "Spazio"
+
+msgid "Service offline or broken"
+msgstr "Servizio Off.line o Fuori Uso"
+
+msgid "Your inbox"
+msgstr "Messaggi in entrata"
+
+msgid "Available actions"
+msgstr "Azioni disponibili"
+
+msgid "Clean"
+msgstr "Svuota"
+
+msgid "New"
+msgstr "Nuovo"
+
+msgid "Received"
+msgstr "Ricevuti"
+
+msgid "Subject"
+msgstr "Oggetto"
+
+msgid "Content"
+msgstr "Contenuto"
+
+msgid "Send message"
+msgstr "Invia messaggio"
+
+msgid "Your inbox is empty."
+msgstr "Non hai messaggi in entrata."
+
+msgid "MUC administration"
+msgstr "Amministrazione MUC"
+
+msgid "You administrate this room"
+msgstr "Amministra questa stanza"
+
+msgid "Enter new subject"
+msgstr "Inserisci il nuovo topic"
+
+msgid "Configuration"
+msgstr "Configurazione"
+
+msgid "Authorizations"
+msgstr "Autorizzazioni"
+
+msgid "Member list"
+msgstr "Lista utenti"
+
+msgid "Owner list"
+msgstr "Lista gestori"
+
+msgid "Administrator list"
+msgstr "Lista amministratori"
+
+msgid "Outcast list"
+msgstr "Lista dei reietti"
+
+msgid "Add an input"
+msgstr "Aggiungi un input"
+
+msgid "Destroy this MUC"
+msgstr "Distruggi questa MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Si, esegui!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Il tuo amico sta guardando la conversazione."
+
+msgid "Your friend is writing a message..."
+msgstr "Il tuo amico sta scrivendo un messaggio"
+
+msgid "Your friend stopped writing a message."
+msgstr "Il tuo amico ha smesso di scrivere un messaggio"
+
+msgid "Your friend is doing something else."
+msgstr "Il tuo amico sta facendo altro."
+
+msgid "Your friend closed the chat."
+msgstr "Il tuo amico ha chiuso la chat"
+
+msgid "Requesting this service..."
+msgstr "Richiesta del servizio"
+
+msgid "Loading"
+msgstr "Carcamento"
+
+msgid "joined the chat room"
+msgstr "Si è aggiunto alla chat room"
+
+msgid "left the chat room"
+msgstr "ha lasciato la chat room"
+
+msgid "no status"
+msgstr "nessuno status"
+
+msgid "has been kicked"
+msgstr "è stato cacciato"
+
+msgid "has been banned"
+msgstr "è stato escluso"
+
+msgid "no reason"
+msgstr "nessuna ragione"
+
+msgid "Communicate with the entire world!"
+msgstr "Comunica con l'intero mondo"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Ti permette di entrare in contatto con i milioni di utenti che utilizzano XMPP (Jabber) come fai tu con Jappix. Unisciti a noi."
+
+msgid "Hi there!"
+msgstr "Ciao!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Benvenuti su %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Accedi al tuo account XMPP esistente oppure creane uno nuovo gratuitamente!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix è un progetto open-source di PostPro, un'organizzazione senza scopo di lucro che ci è stata molto d'aiuto."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Accedi utilizzando il tuo account XMPP. Puoi anche utilizzare %s per accedere una chat di gruppo."
+
+msgid "Previous"
+msgstr "Precedente"
+
+msgid "General"
+msgstr "Generale"
+
+msgid "Advanced"
+msgstr "Avanzato"
+
+msgid "Resource"
+msgstr "Risorsa"
+
+msgid "Priority"
+msgstr "Priorità"
+
+msgid "Low"
+msgstr "Inferiore"
+
+msgid "Medium"
+msgstr "Medio"
+
+msgid "High"
+msgstr "Superiore"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Inserisci la chat di gruppo a cui vuoi unirti ed il nick che vuoi usare. Puoi anche ritornare ad %s."
+
+msgid "login page"
+msgstr "pagina per login"
+
+msgid "Share this link with your friends:"
+msgstr "Condividi questo link con i tuoi amici"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Registra un nuovo account XMPP/Jabber per unirti ad i tuoi amici nel tuo cloud sociale. E' semplice!"
+
+msgid "Required"
+msgstr "Richiesto"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Registrazione completata. Ecco il tuo indirizzo XMPP:"
+
+msgid "Manager"
+msgstr "Amministrazione"
+
+msgid "Project"
+msgstr "Progetto"
+
+msgid "Encrypted"
+msgstr "Criptato"
+
+msgid "Unencrypted"
+msgstr "Non criptato"
+
+msgid "Where are you?"
+msgstr "Dove sei?"
+
+msgid "What's up with you?"
+msgstr "Che passa?"
+
+msgid "Fetching the social channel..."
+msgstr "Sto scaricando il canale sociale..."
+
+msgid "You are synchronized with your network."
+msgstr "Sei sincronizzato con la tua rete."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Impossibile inviare: puoi solo ricevere gli avvisi!"
+
+msgid "Media viewer"
+msgstr "Visualizzatore di Media"
+
+msgid "Browse"
+msgstr "Sfoglia"
+
+msgid "Command"
+msgstr "Comando"
+
+msgid "Subscribe"
+msgstr "Sottoscrivi"
+
+msgid "Join"
+msgstr "Unisciti"
+
+msgid "Automatic"
+msgstr "Automatico"
+
+msgid "Search"
+msgstr "Cerca"
+
+msgid "No result!"
+msgstr "nessun risultato"
+
+msgid "No notifications."
+msgstr "Niente avvisi."
+
+msgid "would like to add you as a friend."
+msgstr "vorrebbe aggiungerti come amico."
+
+msgid "would like you to join this chatroom:"
+msgstr "vorrebbe che lo raggiungessi in questa chatroom:"
+
+msgid "Do you accept?"
+msgstr "Accetti?"
+
+msgid "Yes"
+msgstr "Si"
+
+msgid "No"
+msgstr "No"
+
+msgid "would like to get authorization."
+msgstr "vorrebbe essere autorizzato ad aggiungerti."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Vuoi vedere gli amici suggeriti da %s?"
+
+msgid "Submit"
+msgstr "Invia"
+
+msgid "Client"
+msgstr "Cliente"
+
+msgid "System"
+msgstr "Sistema"
+
+msgid "Local time"
+msgstr "Ora Locale"
+
+msgid "Comments"
+msgstr "Commenti"
+
+msgid "User profile"
+msgstr "Profilo utente"
+
+msgid "See his/her position on the globe"
+msgstr "Visualizza la sua posizione nel modo"
+
+msgid "Confirm"
+msgstr "Conferma"
+
+msgid "anonymous mode"
+msgstr "modalità anonima"
+
+msgid "Groups"
+msgstr "Gruppi"
+
+msgid "Unclassified"
+msgstr "Non classificato"
+
+msgid "Authorize"
+msgstr "Autorizza"
+
+msgid "Ask for authorization"
+msgstr "Chiedi l'autorizzazione"
+
+msgid "Unblock"
+msgstr "Sblocca"
+
+msgid "Prohibit"
+msgstr "Proibisci"
+
+msgid "Block"
+msgstr "Blocca"
+
+msgid "Chat"
+msgstr "Chat"
+
+msgid "Groupchat"
+msgstr "Chat di gruppo"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobile"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Mobile"
+
+msgid "Please wait..."
+msgstr "Attendere..."
+
+msgid "Please enable JavaScript"
+msgstr "Attiva i javascript"
+
+msgid "Your channel"
+msgstr "Il tuo canale"
+
+msgid "Channel of"
+msgstr "Canale di"
+
+msgid "More notices..."
+msgstr "Altre informazioni"
+
+msgid "Attach a file"
+msgstr "Allega un file"
+
+msgid "Send"
+msgstr "Invia"
+
+msgid "Unattach the file"
+msgstr "Rimuovi il file allegato"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "C'è stato un errore durante il caricamento del tuo file: forse è troppo grande (%s al massimo) o non permesso!"
+
+msgid "Authorization failed"
+msgstr "Autorizzazione fallita"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrazione fallita, scegli un nuovo nome utente"
+
+msgid "Service unavailable"
+msgstr "Servizio non disponibile"
+
+msgid "Internal server error, try later"
+msgstr "Internal server error, prova più tardi"
+
+msgid "Your form has been sent."
+msgstr "Il tuo modulo è stato inviato."
+
+msgid "Application"
+msgstr "Applicazione"
+
+msgid "XMPP links"
+msgstr "Links XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Apri i collegamenti XMPP con Jappix"
+
+msgid "changed the subject to:"
+msgstr "Cambia il soggetto a:"
+
+msgid "Welcome!"
+msgstr "Benvenuto!"
+
+msgid "Friends"
+msgstr "Amici"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Benvenuto su Jappix, il tuo cloud sociale personale!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Prima di iniziare ad utilizzare Jappix, devi cambiare alcune impostazione, aggiungere nuovi contatti e completare il tuo profilo."
+
+msgid "Enable notification sounds"
+msgstr "Attiva avvisi sonori"
+
+msgid "Share your position on the globe"
+msgstr "Condividi la tua posizione attuale"
+
+msgid "Offline friends"
+msgstr "Amici non in linea"
+
+msgid "Don't hide offline friends"
+msgstr "Non nascondere amici non in linea"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Utilizza questa utilità per cercare i tuoi amici sul server che stai utilizzando adesso, o aggiungili dopo."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Ben fatto! Adesso, puoi condividere Jappix con i tuoi amici!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Quando premerai il tasto salva, l'editor del tuo profilo verrà aperto. Buona socializzazione!"
+
+msgid "Share Jappix on %s"
+msgstr "Condividi Jappix on %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Using Jappix, an open social platform. I am %s!"
+
+msgid "Unknown name"
+msgstr "Nome sconosciuto"
+
+msgid "Unknown country"
+msgstr "Nazione sconosciuta"
+
+msgid "Click to enable"
+msgstr "Clicca per attivare"
+
+msgid "Click to disable"
+msgstr "Clicca per disattivare"
+
+msgid "Installation"
+msgstr "Installazione"
+
+msgid "Jappix installation"
+msgstr "Installazione Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Benvenuti nella installazione di Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Questo strumento ti aiuterà ad installare velocemente Jappix, il primo platform sociale basato su XMPP, sul tuo server. Non è richiesta alcuna conoscenza tecnica."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Diamo un occhiata ai passi per l'installazione:"
+
+msgid "Welcome"
+msgstr "Benvenuto"
+
+msgid "Storage configuration"
+msgstr "Configurazione per lo storage dei dati"
+
+msgid "Administrator account"
+msgstr "Account amministrativo"
+
+msgid "Main configuration"
+msgstr "Configurazione principale"
+
+msgid "Hosts configuration"
+msgstr "Configurazione degli hosts"
+
+msgid "Services installation"
+msgstr "Installazione servizi"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Se la lingua corrente non riflette la tua (%1s), puoi fare in modo che Jappix sia tradotto in %2s e sarà salvato."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Se hai bisogno di aiuto per l'installazione e la configurazione di Jappix, puoi utilizzare la nostra documentazione online disponibile qui: "
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "E' tempo di costruire il tuo social cloud: vai al prossimo punto!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix salva i dati persistenti (come file condivisi, registri delle conversazioni, la tua musica e la sua configurazione) dentro una singola cartella sicura."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix deve avere le autorizzazioni adeguate per scrivere in questa cartella per creare le sotto-directory necessarie. Se no, devi modificare le autorizzazioni per %1s o cambiare il suo proprietario a %2s (dipende anche dalla tua configurazione)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "La directory è scrivibile, puoi continuare!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix ti offre la possibilità controllare la configurazione di Jappix, installare nuove plugins e cercare aggiornamenti. Ecco perchè devi creare un account amministrativo per accedere all'Amministrazione."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Quando Jappix sarà installato, semplicemente clicca sul link “Amministrazione” nella home page per accedervi."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Opps, hai dimenticato qualche cosa o le due password non coincidono!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix necessita l'impostazione di alcuni dati per funzionare correttamente. Perpiacere cambia i dati seguenti (o mantieni le impostazioni di default)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Nota che se non specifichi una delle impostazioni obbligatorie, sarà automaticamente completata con il valore di default."
+
+msgid "User"
+msgstr "Utente"
+
+msgid "Service"
+msgstr "Servizio"
+
+msgid "Service name"
+msgstr "Nome del servizio"
+
+msgid "Service description"
+msgstr "Descrizione del servizio"
+
+msgid "Connection"
+msgstr "Connessione"
+
+msgid "Lock the host"
+msgstr "Blocca il nome dell'host"
+
+msgid "Anonymous mode"
+msgstr "Modalità anonima"
+
+msgid "Registration allowed"
+msgstr "Registrazione permessa"
+
+msgid "Use a proxy"
+msgstr "Utilizza un proxy"
+
+msgid "Encryption"
+msgstr "Crittografia"
+
+msgid "HTTPS storage"
+msgstr "Usa HTTPS per l'archiviazione"
+
+msgid "Force HTTPS"
+msgstr "Forza HTTPS"
+
+msgid "Compression"
+msgstr "Compressione"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Questa pagina serve a specificare i server principali a cui Jappix si connette. Puoi lasciarli come sono e continuare se vuoi usare il servizio ufficiale."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Forse non sai cos'è un server BOSH? E' un relay tra Jappix è il server XMPP, che è per il momento necessario per limitazioni tecniche."
+
+msgid "Main host"
+msgstr "Host del server"
+
+msgid "Groupchat host"
+msgstr "Host del server MUC"
+
+msgid "Anonymous host"
+msgstr "Host per le connessioni anonime"
+
+msgid "Directory host"
+msgstr "Server per la Directory degli utenti."
+
+msgid "BOSH host"
+msgstr "Server BOSH"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Puoi installare del software opzionale sul tuo server, per estendere le funzioni di Jappix. Alcune altre potrebbero essere modificate, per via delle restrizioni di sicurezza impostate di default."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Per completare questa operazione devi essere in grado di accedere al tuo server tramite terminale come root, Ricordati che questo è facoltativo, Jappix funziona anche senza questi moduli, ma alcune delle sue caratteristiche non saranno disponibili."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Dopo che completi il setup, Jappix generà i files di cache. Potrebbe essere un processo abbastanza lento, semplicemente aspetta che l'applicazione sia mostrata senza premere nessun tasto."
+
+msgid "Thanks for using Jappix!"
+msgstr "Grazie per aver scelto Jappix!"
+
+msgid "Next"
+msgstr "Continua"
+
+msgid "Finish"
+msgstr "Completa"
+
+msgid "Check again"
+msgstr "Controlla ancora"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "La cartella non è scrivibile, imposta le autorizzazioni corrette per %s."
+
+msgid "%s is installed on your system."
+msgstr "%s è installato sul tuo sistema."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s non è installato sul tuo sistema, dovresti installare %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "La dimensione massima degli upload per PHP non è sufficente (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "La dimensione massima degli upload per PHP non è sufficente (%s), impostala a %2s in %3s."
+
+msgid "Jappix manager"
+msgstr "Manager di Jappix"
+
+msgid "Manager access"
+msgstr "Access del manager"
+
+msgid "Statistics"
+msgstr "Statistiche"
+
+msgid "Hosts"
+msgstr "Host"
+
+msgid "Design"
+msgstr "Progetto"
+
+msgid "Repeat"
+msgstr "Ripeti"
+
+msgid "All"
+msgstr "Tutti"
+
+msgid "Horizontal"
+msgstr "Orizzontale"
+
+msgid "Vertical"
+msgstr "Verticale"
+
+msgid "Center"
+msgstr "Centro"
+
+msgid "Left"
+msgstr "Sinistra"
+
+msgid "Right"
+msgstr "Destra"
+
+msgid "Top"
+msgstr "In Cima"
+
+msgid "Bottom"
+msgstr "In Fondo"
+
+msgid "Adapt"
+msgstr "Adatta"
+
+msgid "Color"
+msgstr "Colore"
+
+msgid "Users"
+msgstr "Utente"
+
+msgid "Updates"
+msgstr "Aggiornamenti"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Questa è una area ristretta: solo gli utenti autorizzati possono gestire questo nodo Jappix"
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Perpiacere utilizza il modulo qui sotto per accedere al Pannello amministrativo."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Per aumentare la sicurezza, le sessioni sono a tempo limitato e quando chiudi il tuo browser, sarai disconnesso."
+
+msgid "Credentials"
+msgstr "Informazioni di accesso"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Sei stato disconnesso. Arrivederci!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Opps, non sei stato riconusciuto come un amministratore valido. Controlla le tue credenziali!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Puoi trovare qui sotto, le statistiche base ottenute da Jappix."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Cambia qui la configurazione del tuo nodo Jappix."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Cambia qui gli hosts XMPP serviti da questo nodo Jappix."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Tutti i file salvati di questo nodo Jappix possono essere controllati da questa pagina: perpiacere scegli una sotto-directory ed inizia a modificare il suo contenuto!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix è completamente personalizzabile: puoi cambiare qui il suo look."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Il formato di questa immagine non è valido, perpiacere utilizza PNG, GIF oppure JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "L'immagine non è stata caricata correttamente, Riprova?"
+
+msgid "Your image was added to the list!"
+msgstr "La tua immagina è stata aggiunta alla lista!"
+
+msgid "Changes saved!"
+msgstr "Modifiche salvate!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Puoi definire più di un amministratore per questo nodo Jappix e cambiare qui le passwords associate."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Aggiorna qui il tuo nodo Jappix, puoi anche controllare se una nuova versione e disponibile. Le informazioni sulle ultime versioni sono disponibili solo in inglese."
+
+msgid "Access statistics"
+msgstr "Statistiche sugli accessi"
+
+msgid "Share statistics"
+msgstr "Condividi le statistiche"
+
+msgid "Other statistics"
+msgstr "Altre statistiche"
+
+msgid "January"
+msgstr "Gennaio"
+
+msgid "February"
+msgstr "Febbraio"
+
+msgid "March"
+msgstr "Marzo"
+
+msgid "April"
+msgstr "Aprile"
+
+msgid "May"
+msgstr "Maggio"
+
+msgid "June"
+msgstr "Giugno"
+
+msgid "July"
+msgstr "Luglio"
+
+msgid "August"
+msgstr "Agosto"
+
+msgid "September"
+msgstr "Settembre"
+
+msgid "October"
+msgstr "Ottobre"
+
+msgid "November"
+msgstr "Novembre"
+
+msgid "December"
+msgstr "Dicembre"
+
+msgid "Monday"
+msgstr "Lunedì"
+
+msgid "Tuesday"
+msgstr "Martedì"
+
+msgid "Wednesday"
+msgstr "Mercoledì"
+
+msgid "Thursday"
+msgstr "Giovedì"
+
+msgid "Friday"
+msgstr "Venerdì"
+
+msgid "Saturday"
+msgstr "Sabato"
+
+msgid "Sunday"
+msgstr "Domenica"
+
+msgid "Total"
+msgstr "Totali"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Registri"
+
+msgid "Music"
+msgstr "Musica"
+
+msgid "Backgrounds"
+msgstr "Sfondi"
+
+msgid "Share"
+msgstr "Condividi"
+
+msgid "Background"
+msgstr "Sfondo"
+
+msgid "Notice"
+msgstr "Avviso"
+
+msgid "Your design preferences have been saved!"
+msgstr "Le tue preferenza per il design sono state salvate!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Perpiacere controlla i tuoi dati inseriti: vi sono dei valori mancanti!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Cambia lo sfondo del tuo nodo Jappix in questa pagina. Puoi scegliere un colore una immagine caricata."
+
+msgid "Use default background"
+msgstr "Utilizza lo sfondo di default"
+
+msgid "Use your own image"
+msgstr "Utilizza una tua immagine"
+
+msgid "Select a background to use and change the display options."
+msgstr "Scegli uno sfondo da utilizzare è cambia le opzioni di display."
+
+msgid "Use your own color"
+msgstr "Utilizza un tuo colore personalizzato"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Inserisci qui il valore esadecimale del colore che vuoi usare come background."
+
+msgid "Manage backgrounds"
+msgstr "Controlla sfondi"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Puoi aggiungere un nuovo background alla lista con questa utilità. Perpiacere invia un'immagine valida."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Se vuoi rimuovere alcuni sfondi, utilizza browser qui sotto."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Imposta un avviso mostrato nella homepage, per tutti i tuoi utenti come un avviso/messaggio importante con questa utilità."
+
+msgid "Simple notice"
+msgstr "Avviso semplice"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Questo avviso mostra solo testo semplice, codice HTML non è permesso!"
+
+msgid "Advanced notice"
+msgstr "Avviso avanzato"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Puoi personalizzare i tuoi avvisi con HTML, CSS e Javascript incluso, ma è richiesta la conoscenza dei rispettivi linguaggi."
+
+msgid "Available updates"
+msgstr "Aggiornamenti disponibili"
+
+msgid "What's new?"
+msgstr "Cosa c'è di nuovo?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Le cartelle per l'archiviazioni non sono scrivibili, perpiacere imposta le autorizzazioni corrette!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s può causare problemi al proxy, perpiacere incrementa il valore %2s a %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Stai utilizzando una versione ancora non definitiva di Jappix. La puoi aggiornare tramite il nostro repositorio, eseguendo: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Una nuova versione di Jappix è disponibile! Controlla il registro delle modifica ed avvia l'aggiornamento!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "La tua versione è obsoleta. Aggiornala a %s cliccando qui!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "La tua versione sembra essere aggiornata, ma puoi controllare gli aggiornamenti manualmente cliccando qui."
+
+msgid "Check for updates"
+msgstr "Controlla aggiornamenti"
+
+msgid "Update in progress"
+msgstr "Aggiornamento in corso"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix è stato aggiornato: Stai utilizzando l'ultima version. Divertiti!"
+
+msgid "The update has failed! Please try again later."
+msgstr "L'aggiornamento è fallito! Perpiacere, riprova più tardi."
+
+msgid "Downloading package..."
+msgstr "Sto scaricando il pacchetto..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Rimozione dei file di sistema di Jappix..."
+
+msgid "Extracting package..."
+msgstr "Sto estraendo il pacchetto..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Sto rigenerando l'albero delle cartelle di salvataggio..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix è adesso aggiornato!"
+
+msgid "Aborted: socket error!"
+msgstr "Interrotto: errore del socket!"
+
+msgid "Aborted: buffer error!"
+msgstr "Interrotto: errore buffer!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Interrotto: il percorso non è scrivibile!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Interrotto: non è stato possibile estrarre il pacchetto!"
+
+msgid "Visits"
+msgstr "Visite"
+
+msgid "Daily"
+msgstr "Giornaliero"
+
+msgid "Weekly"
+msgstr "Settimanale"
+
+msgid "Monthly"
+msgstr "Mensile"
+
+msgid "Yearly"
+msgstr "Annuale"
+
+msgid "Size"
+msgstr "Dimensione"
+
+msgid "Clean everything"
+msgstr "Ripristina tutto"
+
+msgid "Purge cache"
+msgstr "Pulisci la cache"
+
+msgid "Purge logs"
+msgstr "Cancella i registri"
+
+msgid "Purge updates"
+msgstr "Pulisci la cartella degli aggiornamenti"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Ho pulito la cartella degli archivi da te indicata!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "La manutenzione di Jappix è importante, tieni pulite le cartelle di archiviazione!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Carica la tua musica (OGG Vorbis, MP3 o WAV) per sentirla da Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Il file che vuoi caricare deve essere più piccolo di %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Puoi controllare qui il contenuto che i tuoi utemti salvano sul server, e rimuore quello indesiderato."
+
+msgid "Title"
+msgstr "Titolo"
+
+msgid "Artist"
+msgstr "Artista"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "File"
+
+msgid "Upload"
+msgstr "Carica"
+
+msgid "The folder is empty."
+msgstr "La cartella è vuota."
+
+msgid "The music could not be received, please retry!"
+msgstr "La musica non è stata caricata correttamente, perpiacere riprova!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Questo non è un file musicale valido, perpiacere codificalo in OGG Vorbis, MP3 oppure WAV!"
+
+msgid "Your music has been added!"
+msgstr "Ho aggiunto la tua musica!"
+
+msgid "The selected elements have been removed."
+msgstr "Gli elementi selezionati sono stati rimossi."
+
+msgid "You must select elements to remove!"
+msgstr "Devi selezionare almeno un elemento da rimuovere."
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Aggiungi un nuovo utente con questa utilità oppure cambia la password di uno esistente. Perpiacere utilizza una password sicura."
+
+msgid "Manage"
+msgstr "Amministra"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Rimuovi gli utenti amministrativi con questa utilità. Nota che deve essere presente almeno un utente amministrativo."
+
+msgid "The user has been added!"
+msgstr "L'utente è stato aggiunto!"
+
+msgid "The chosen users have been removed."
+msgstr "Gli utenti selezionati sono stati rimossi."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Devi selezionare uno o più utenti da rimuovere!"
+
+msgid "Yesterday"
+msgstr "Ieri"
+
+msgid "%s days ago"
+msgstr "%s giorni fa'"
+
+msgid "User currently active"
+msgstr "Utente correntemente attivo"
+
+msgid "Last seen: %s"
+msgstr "Ultimo accesso: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inattivo da: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Il tuo contatto sembra non aver ricevuto il tuo o i tuoi messagi!"
+
+msgid "Static content server"
+msgstr "Server per il contenuto statico"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Questo è il server per il contenuto statico di %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Amici suggeriti"
+
+msgid "Check all"
+msgstr "Seleziona tutte le opzioni"
+
+msgid "Uncheck all"
+msgstr "Deseleziona tutte le opzioni"
+
+msgid "Choose"
+msgstr "Scegli"
+
+msgid "List name"
+msgstr "Nome lista"
+
+msgid "Allow"
+msgstr "Permetti"
+
+msgid "Deny"
+msgstr "Rifiuta"
+
+msgid "Group"
+msgstr "Gruppo"
+
+msgid "Subscription"
+msgstr "Sottoscrizione"
+
+msgid "Both"
+msgstr "Entrambi"
+
+msgid "From"
+msgstr "Da"
+
+msgid "Everybody"
+msgstr "Tutti quanti"
+
+msgid "Send messages"
+msgstr "Invia messaggi"
+
+msgid "Send queries"
+msgstr "Invia richieste"
+
+msgid "See my status"
+msgstr "Vedi il mio stato"
+
+msgid "Send his/her status"
+msgstr "Invia il suo status"
+
+msgid "Everything"
+msgstr "Tutto"
+
+msgid "Item"
+msgstr "Oggetto"
+
+msgid "Order"
+msgstr "Ordina"
+
+msgid "Active for this session"
+msgstr "Attivo per questa sessione"
+
+msgid "Always active"
+msgstr "Sempre attivo"
+
+msgid "User directory"
+msgstr "Cartella utenti"
+
+msgid "Search a friend"
+msgstr "Cerca un amico"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Questa caratteristica non è implementata dal client del recipiente oppure il suo server e quindi non può essere processata."
+
+msgid "This is a repeat from %s"
+msgstr "Questa è una ripetizione da %s"
+
+msgid "Loading comments..."
+msgstr "Sto caricando i commenti..."
+
+msgid "Type your comment here..."
+msgstr "Inserisci qui il tuo commento..."
+
+msgid "Could not get the comments!"
+msgstr "Non ho potuto ottenere nessun commento!"
+
+msgid "Show comments"
+msgstr "Mostra commenti"
+
+msgid "Send him/her a message"
+msgstr "Invia un messaggio a lui/lei"
+
+msgid "Start a chat with him/her"
+msgstr "Inizia una chat con lui/lei"
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix è un platform sociale no-profit, che puoi accedere duvunque tu sia, qualsiasi volta tu abbia voglia di communicare con qualcuno."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/ja/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/ja/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..e09eddc
Binary files /dev/null and b/jappixmini/jappix/lang/ja/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/ja/LC_MESSAGES/main.po b/jappixmini/jappix/lang/ja/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..bc1751f
--- /dev/null
@@ -0,0 +1,1870 @@
+# Japanese translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "ブラウザの設定でJavaScriptが無効になっている為、Jappixを起動できません! JavaScriptを有効にしてください。"
+
+msgid "An open social network"
+msgstr "オープンソーシャルネットワーク"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappixはネットワークの問題により停止しました。バグか不正なログインです(入力した認証情報を確認してください)。ご不便をおかけして申し訳ありません。"
+
+msgid "The element list on this server could not be obtained!"
+msgstr "このサーバのエレメントリストを取得することができませんでした!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "あなたのパスワードは変更されました。今から新しいパスワードでログインできます。"
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "あなたのXMPPアカウントは正常に削除されました。さようなら!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "XMPPアカウントをログアウトしました。良い一日を!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "参加するルームが存在しません。作成する必要があります!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "グループチャットは削除されました、今から誰でも再作成を行うことが出来ます。"
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "ユーザはあなたの望むチャットルームに到着することができませんでした。"
+
+msgid "Please enter the group chat address to join."
+msgstr "参加するグループチャットアドレスを入力してください。"
+
+msgid "Please enter your nickname to join %s."
+msgstr "%s に参加するニックネームを入力してください。"
+
+msgid "This room (%s) is protected with a password."
+msgstr "このチャットルーム (%s) はパスワードで保護されています。"
+
+msgid "Your browser is out of date!"
+msgstr "ブラウザバージョンが古いです!"
+
+msgid "Last %s version is better!"
+msgstr "バージョン %s を推奨します。"
+
+msgid "Login"
+msgstr "ログイン"
+
+msgid "Register"
+msgstr "登録"
+
+msgid "Here we go!"
+msgstr "さあ、はじめよう!"
+
+msgid "Server"
+msgstr "サーバー"
+
+msgid "Password"
+msgstr "パスワード"
+
+msgid "Remember me"
+msgstr "記憶する"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "このツールは無効になっている為、使用することができません!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "ネットワークの問題により切断されました。どうしますか?"
+
+msgid "Reconnect"
+msgstr "再接続"
+
+msgid "Messages"
+msgstr "メッセージ"
+
+msgid "Profile"
+msgstr "プロフィール"
+
+msgid "Options"
+msgstr "オプション"
+
+msgid "Disconnect"
+msgstr "切断"
+
+msgid "Filter"
+msgstr "フィルター"
+
+msgid "Add a friend"
+msgstr "友達を追加"
+
+msgid "Your groupchats"
+msgstr "グループチャット"
+
+msgid "Manage your favorite groupchats"
+msgstr "お気に入りのグループチャットを管理"
+
+msgid "More stuff"
+msgstr "もっと多く"
+
+msgid "Show all friends"
+msgstr "全ての友達を見る"
+
+msgid "Only show connected friends"
+msgstr "オンラインの友達のみ表示"
+
+msgid "Message archives"
+msgstr "メッセージアーカイブ"
+
+msgid "Date"
+msgstr "日付"
+
+msgid "Please select a friend to view the chat history."
+msgstr "友達を選択するとチャットの履歴が見れます"
+
+msgid "Nothing found for: %s"
+msgstr "見つかりません: %s"
+
+msgid "A short message?"
+msgstr "短いメッセージですか?"
+
+msgid "How are you?"
+msgstr "ご機嫌いかが?"
+
+msgid "What are you doing?"
+msgstr "なにしてる?"
+
+msgid "Join a chat"
+msgstr "チャットに参加"
+
+msgid "Status"
+msgstr "ステータス"
+
+msgid "Available"
+msgstr "オンライン"
+
+msgid "Talkative"
+msgstr "おしゃべり"
+
+msgid "Away"
+msgstr "離席"
+
+msgid "Not available"
+msgstr "対応不能"
+
+msgid "Busy"
+msgstr "多忙"
+
+msgid "Mood"
+msgstr "ムード"
+
+msgid "None"
+msgstr "なし"
+
+msgid "Crazy"
+msgstr "狂気"
+
+msgid "Excited"
+msgstr "興奮"
+
+msgid "Playful"
+msgstr "冗談半分"
+
+msgid "Happy"
+msgstr "幸福"
+
+msgid "Shocked"
+msgstr "ショック"
+
+msgid "Hot"
+msgstr "元気"
+
+msgid "Sad"
+msgstr "悲しい"
+
+msgid "Amorous"
+msgstr "恋心"
+
+msgid "Confident"
+msgstr "大胆"
+
+msgid "Activity"
+msgstr "アクティビィティ"
+
+msgid "Chores"
+msgstr "雑用"
+
+msgid "Drinking"
+msgstr "飲酒"
+
+msgid "Eating"
+msgstr "食事"
+
+msgid "Exercising"
+msgstr "運動"
+
+msgid "Grooming"
+msgstr "訓練"
+
+msgid "Appointment"
+msgstr "予約"
+
+msgid "Inactive"
+msgstr "無効"
+
+msgid "Relaxing"
+msgstr "リラックス"
+
+msgid "Talking"
+msgstr "会話"
+
+msgid "Traveling"
+msgstr "旅行"
+
+msgid "Working"
+msgstr "仕事"
+
+msgid "View profile"
+msgstr "プロフィールを見る"
+
+msgid "Repeat this notice"
+msgstr "お知らせを繰り返す"
+
+msgid "Remove this notice"
+msgstr "お知らせを削除"
+
+msgid "Your profile"
+msgstr "あなたのプロフィール"
+
+msgid "Identity"
+msgstr "身元"
+
+msgid "Profile image"
+msgstr "プロフィール画像"
+
+msgid "Others"
+msgstr "その他"
+
+msgid "Personal"
+msgstr "個人"
+
+msgid "Complete name"
+msgstr "氏名"
+
+msgid "Nickname"
+msgstr "ニックネーム"
+
+msgid "First name"
+msgstr "名"
+
+msgid "Last name"
+msgstr "姓"
+
+msgid "Date of birth"
+msgstr "誕生日"
+
+msgid "Contact"
+msgstr "連絡先"
+
+msgid "E-mail"
+msgstr "Eメール"
+
+msgid "Phone"
+msgstr "電話"
+
+msgid "Website"
+msgstr "WEBサイト"
+
+msgid "Current"
+msgstr "カレント"
+
+msgid "Delete"
+msgstr "削除"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "残念!あなたの情報カードにイメージが定義されていません"
+
+msgid "Address"
+msgstr "アドレス"
+
+msgid "Street"
+msgstr "番地"
+
+msgid "City"
+msgstr "市町村"
+
+msgid "Postal code"
+msgstr "郵便番号"
+
+msgid "Country"
+msgstr "国"
+
+msgid "Biography"
+msgstr "自己紹介"
+
+msgid "Important notice"
+msgstr "重要なお知らせ"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "みんながアクセスする為、プロフィール情報を書き込むときは注意してください。(あなたが公開を望まない情報もあります)"
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "XMPPはプライベートではありません。パブリックプロファイル(vCard)を選択してください。"
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "他のユーザが簡単に識別できるようにプロファイルイメージ(最大 %s)をアップロードする事をお勧めします。"
+
+msgid "Save"
+msgstr "保存"
+
+msgid "Cancel"
+msgstr "キャンセル"
+
+msgid "Edit options"
+msgstr "オプション編集"
+
+msgid "Channel"
+msgstr "チャンネル"
+
+msgid "Commands"
+msgstr "コマンド"
+
+msgid "Sounds"
+msgstr "サウンド"
+
+msgid "Privacy"
+msgstr "プライバシー"
+
+msgid "Message archiving"
+msgstr "メッセージアーカイブ"
+
+msgid "Store a history of your chats"
+msgstr "チャット履歴を保持する"
+
+msgid "Geolocation"
+msgstr "位置情報"
+
+msgid "Empty"
+msgstr "空"
+
+msgid "Empty channel"
+msgstr "空のチャンネル"
+
+msgid "Persistent"
+msgstr "持続"
+
+msgid "Maximum notices"
+msgstr "お知らせの最大数"
+
+msgid "Account"
+msgstr "アカウント"
+
+msgid "Change password"
+msgstr "パスワード変更"
+
+msgid "Delete account"
+msgstr "アカウント削除"
+
+msgid "Old"
+msgstr "古い"
+
+msgid "New (2 times)"
+msgstr "新しい(2回)"
+
+msgid "Continue"
+msgstr "次"
+
+msgid "To"
+msgstr "宛先"
+
+msgid "Close"
+msgstr "閉じる"
+
+msgid "unknown"
+msgstr "不明"
+
+msgid "Unavailable"
+msgstr "使用出来ません"
+
+msgid "is now"
+msgstr "新規"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "アバターのアップロードが完了するのを待ってください…"
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "美しい新規プロファイルイメージはここにあります"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "このイメージはサポートされていないか、サイズが間違っています"
+
+msgid "Reply"
+msgstr "返信"
+
+msgid "Error"
+msgstr "エラー"
+
+msgid "Click here to solve the error"
+msgstr "クリックしてエラーを修正してください"
+
+msgid "You"
+msgstr "あなた"
+
+msgid "Remove"
+msgstr "削除"
+
+msgid "Rename"
+msgstr "名前変更"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "こんにちは、わたしは %s です。あなたを新しい友人に追加したいです。"
+
+msgid "Smiley insertion"
+msgstr "顔文字を挿入"
+
+msgid "Change style"
+msgstr "スタイル変更"
+
+msgid "Text in bold"
+msgstr "太字"
+
+msgid "Text in italic"
+msgstr "イタリック"
+
+msgid "Underlined text"
+msgstr "下線"
+
+msgid "Save chat"
+msgstr "チャットを保存"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "チャット履歴を取得するには以下のリンクをクリックしてしばらく待ちます。次に再度クリックしてファイルを取得します。"
+
+msgid "This chat is empty!"
+msgstr "このチャットは空です"
+
+msgid "Generate file!"
+msgstr "ファイルを生成!"
+
+msgid "Download file!"
+msgstr "ファイルをダウンロード!"
+
+msgid "Clean current chat"
+msgstr "カレントチャットをクリア"
+
+msgid "View chat history"
+msgstr "会話履歴を参照"
+
+msgid "Show user profile"
+msgstr "ユーザープロフィールを表示"
+
+msgid "Add this contact to your friends"
+msgstr "連絡先に友達を追加"
+
+msgid "Add this groupchat to your favorites"
+msgstr "お気に入りにグループチャットを追加"
+
+msgid "All tabs"
+msgstr "全てのタブ"
+
+msgid "Close this tab"
+msgstr "このタブを閉じる"
+
+msgid "no subject defined for this room."
+msgstr "このルームには件名がありません。"
+
+msgid "Administration panel for this room"
+msgstr "この部屋の管理パネル"
+
+msgid "Moderators"
+msgstr "モデレータ"
+
+msgid "Participants"
+msgstr "参加者"
+
+msgid "Visitors"
+msgstr "傍聴者"
+
+msgid "Manage favorite rooms"
+msgstr "お気に入りの部屋の管理"
+
+msgid "Change favorites"
+msgstr "お気に入りの変更"
+
+msgid "Search a room"
+msgstr "ルームを検索"
+
+msgid "Select a favorite"
+msgstr "お気に入りを選択"
+
+msgid "Getting the name..."
+msgstr "名前を取得中"
+
+msgid "Gateway"
+msgstr "ゲートウェイ"
+
+msgid "Name"
+msgstr "名前"
+
+msgid "Room"
+msgstr "ルーム"
+
+msgid "Add"
+msgstr "追加"
+
+msgid "Edit"
+msgstr "編集"
+
+msgid "Search a room on"
+msgstr "ルームを検索: "
+
+msgid "No room found on this server."
+msgstr "このサーバーでルームは見つかりませんでした。"
+
+msgid "Service discovery"
+msgstr "サービスディスカバリ"
+
+msgid "Server to query"
+msgstr "サーバーに問い合わせ"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "ごめんね、エンティティがあらゆる結果を返しませんでした!"
+
+msgid "Accounts"
+msgstr "アカウント"
+
+msgid "Authentications"
+msgstr "認証"
+
+msgid "Automation"
+msgstr "自動化"
+
+msgid "Clients"
+msgstr "クライアント"
+
+msgid "Collaboration"
+msgstr "コラボレーション"
+
+msgid "Components"
+msgstr "コンポーネント"
+
+msgid "Rooms"
+msgstr "ルーム"
+
+msgid "Directories"
+msgstr "ディレクトリ"
+
+msgid "Gateways"
+msgstr "ゲートウェイ"
+
+msgid "News"
+msgstr "ニュース"
+
+msgid "Hierarchy"
+msgstr "階層"
+
+msgid "Proxies"
+msgstr "プロキシ"
+
+msgid "Publication/Subscription"
+msgstr "公開/購読"
+
+msgid "Storage"
+msgstr "ストレージ"
+
+msgid "Service offline or broken"
+msgstr "サービスがオフラインか壊れています"
+
+msgid "Your inbox"
+msgstr "受信箱"
+
+msgid "Available actions"
+msgstr "有効な動作"
+
+msgid "Clean"
+msgstr "消去"
+
+msgid "New"
+msgstr "New"
+
+msgid "Received"
+msgstr "受信"
+
+msgid "Subject"
+msgstr "件名"
+
+msgid "Content"
+msgstr "内容"
+
+msgid "Send message"
+msgstr "メッセージを送信"
+
+msgid "Your inbox is empty."
+msgstr "受信箱は空です。"
+
+msgid "MUC administration"
+msgstr "MUC管理"
+
+msgid "You administrate this room"
+msgstr "あなたはこのルームを管理します"
+
+msgid "Enter new subject"
+msgstr "新しい件名を入力してください"
+
+msgid "Configuration"
+msgstr "設定"
+
+msgid "Authorizations"
+msgstr "許可"
+
+msgid "Member list"
+msgstr "メンバーリスト"
+
+msgid "Owner list"
+msgstr "所有者リスト"
+
+msgid "Administrator list"
+msgstr "管理者リスト"
+
+msgid "Outcast list"
+msgstr "追放者リスト"
+
+msgid "Add an input"
+msgstr "入力を追加"
+
+msgid "Destroy this MUC"
+msgstr "このMUCを解散する"
+
+msgid "Yes, let's do it!"
+msgstr "はい、そうします!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "友達は、会話に注意を払っています。"
+
+msgid "Your friend is writing a message..."
+msgstr "友達はメッセージを書いています。"
+
+msgid "Your friend stopped writing a message."
+msgstr "友達はメッセージの書き込みを中断しました。"
+
+msgid "Your friend is doing something else."
+msgstr "友達は何かをしています。"
+
+msgid "Your friend closed the chat."
+msgstr "友達はチャットを閉じました。"
+
+msgid "Requesting this service..."
+msgstr "サービスを要求中..."
+
+msgid "Loading"
+msgstr "読み込み中"
+
+msgid "joined the chat room"
+msgstr "チャットルームに誘う"
+
+msgid "left the chat room"
+msgstr "チャットルームに入室する"
+
+msgid "no status"
+msgstr "ステータスがありません"
+
+msgid "has been kicked"
+msgstr "追い出されました"
+
+msgid "has been banned"
+msgstr "禁止されています"
+
+msgid "no reason"
+msgstr "理由無し"
+
+msgid "Communicate with the entire world!"
+msgstr "全世界とコミュニケーション!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "ここでは XMPPネットワークを使用する何百万人のユーザーと連絡を取ることが出来ます。コミュニティーへの参加は自由です!"
+
+msgid "Hi there!"
+msgstr "こんにちは!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "ようこそ %1s へ、 “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "既存のXMPPアカウントでログインを行うか無料でアカウント作成できます!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "JappixはPostProのオープンソースプロジェクトです。私たちは非営利団体なので助けを求めています。"
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "あなたが作成したXMPPアカウントでログインしてください。%s グループチャットに接続することが出来ます。"
+
+msgid "Previous"
+msgstr "戻る"
+
+msgid "General"
+msgstr "一般"
+
+msgid "Advanced"
+msgstr "高度"
+
+msgid "Resource"
+msgstr "リソース"
+
+msgid "Priority"
+msgstr "優先度"
+
+msgid "Low"
+msgstr "低"
+
+msgid "Medium"
+msgstr "中"
+
+msgid "High"
+msgstr "高"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "接続したいグループチャットとニックネームを入力してください。%sで戻ることができます。"
+
+msgid "login page"
+msgstr "ログインページ"
+
+msgid "Share this link with your friends:"
+msgstr "次のリンクを友達と共有する:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "あなたの友達が接続するには、ソーシャルクラウドでXMPPアカウントの承認を受ける必要があります。手続きは簡単にできます。"
+
+msgid "Required"
+msgstr "要求"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "承認されました。あなたのXMPPアドレスは:"
+
+msgid "Manager"
+msgstr "マネージャー"
+
+msgid "Project"
+msgstr "プロジェクト"
+
+msgid "Encrypted"
+msgstr "暗号化済"
+
+msgid "Unencrypted"
+msgstr "暗号化しない"
+
+msgid "Where are you?"
+msgstr "どこにいますか?"
+
+msgid "What's up with you?"
+msgstr "なにしてる?"
+
+msgid "Fetching the social channel..."
+msgstr "ソーシャルチャンネルを取得..."
+
+msgid "You are synchronized with your network."
+msgstr "ネットワークと同期しました。"
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "何も送信できません: あなたはお知らせのみ受信できます!"
+
+msgid "Media viewer"
+msgstr "メディアビューア"
+
+msgid "Browse"
+msgstr "ブラウズ"
+
+msgid "Command"
+msgstr "コマンド"
+
+msgid "Subscribe"
+msgstr "購読"
+
+msgid "Join"
+msgstr "参加"
+
+msgid "Automatic"
+msgstr "自動"
+
+msgid "Search"
+msgstr "検索"
+
+msgid "No result!"
+msgstr "結果はありません!"
+
+msgid "No notifications."
+msgstr "非通知"
+
+msgid "would like to add you as a friend."
+msgstr "はあなたを友達に追加したがっています。"
+
+msgid "would like you to join this chatroom:"
+msgstr "はあなたをチャットルームに招待しています:"
+
+msgid "Do you accept?"
+msgstr "許可しますか?"
+
+msgid "Yes"
+msgstr "はい"
+
+msgid "No"
+msgstr "いいえ"
+
+msgid "would like to get authorization."
+msgstr "承認を希望します"
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "%s に友達申請をしますか?"
+
+msgid "Submit"
+msgstr "送信"
+
+msgid "Client"
+msgstr "クライアント"
+
+msgid "System"
+msgstr "システム"
+
+msgid "Local time"
+msgstr "ローカル時間"
+
+msgid "Comments"
+msgstr "コメント"
+
+msgid "User profile"
+msgstr "ユーザー情報"
+
+msgid "See his/her position on the globe"
+msgstr "位置を見る"
+
+msgid "Confirm"
+msgstr "確認"
+
+msgid "anonymous mode"
+msgstr "匿名モード"
+
+msgid "Groups"
+msgstr "グループ"
+
+msgid "Unclassified"
+msgstr "秘密ではない"
+
+msgid "Authorize"
+msgstr "承認"
+
+msgid "Ask for authorization"
+msgstr "承認を依頼する。"
+
+msgid "Unblock"
+msgstr "ブロック解除"
+
+msgid "Prohibit"
+msgstr "禁止する"
+
+msgid "Block"
+msgstr "除外"
+
+msgid "Chat"
+msgstr "チャット"
+
+msgid "Groupchat"
+msgstr "グループチャット"
+
+msgid "Jappix Mobile"
+msgstr "Jappixモバイル"
+
+msgid "Desktop"
+msgstr "デスクトップ"
+
+msgid "Mobile"
+msgstr "モバイル"
+
+msgid "Please wait..."
+msgstr "しばらくお待ち下さい..."
+
+msgid "Please enable JavaScript"
+msgstr "JavaScriptを有効にして下さい"
+
+msgid "Your channel"
+msgstr "チャンネル"
+
+msgid "Channel of"
+msgstr "チャンネル: "
+
+msgid "More notices..."
+msgstr "他のお知らせ..."
+
+msgid "Attach a file"
+msgstr "ファイルの添付"
+
+msgid "Send"
+msgstr "送信"
+
+msgid "Unattach the file"
+msgstr "添付ファイルの取り消し"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "ファイルアップロード中にエラーが発生しました:ファイルサイズが大きいかアップロードが禁止されています"
+
+msgid "Authorization failed"
+msgstr "認証失敗"
+
+msgid "Registration failed, please choose a different username"
+msgstr "登録に失敗しました、別のユーザー名を選んでください。"
+
+msgid "Service unavailable"
+msgstr "サービス不能です。"
+
+msgid "Internal server error, try later"
+msgstr "内部サーバーエラー、再度試してください。"
+
+msgid "Your form has been sent."
+msgstr "フォームが送信されました"
+
+msgid "Application"
+msgstr "アプリケーション"
+
+msgid "XMPP links"
+msgstr "XMPPリンク"
+
+msgid "Open XMPP links with Jappix"
+msgstr "JappixでXMPPリンクを開く"
+
+msgid "changed the subject to:"
+msgstr "サブジェクトの変更"
+
+msgid "Welcome!"
+msgstr "ようこそ"
+
+msgid "Friends"
+msgstr "友達"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Jappixへようこそ。ここはあなたのソーシャルクラウドです!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "使用を開始する前に、いくつかの設定変更、検索およびプロフィールを設定する必要があります。"
+
+msgid "Enable notification sounds"
+msgstr "警告音を有効にする"
+
+msgid "Share your position on the globe"
+msgstr "現在位置を共有する"
+
+msgid "Offline friends"
+msgstr "オフラインの友達"
+
+msgid "Don't hide offline friends"
+msgstr "オフラインの友達を隠す"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "このツールを使用することでサーバ上の友達の検索したり、追加することが可能になります。"
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "よくできました!あなたは友達とJappixで共有できます。"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "セーブボタンを押すとプロファイルエディターが起動します。幸せなお付き合いを!"
+
+msgid "Share Jappix on %s"
+msgstr "%sとJappixを共有しました"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "私は%sです。オープンソーシャルプラットフォームJappixを使用しています"
+
+msgid "Unknown name"
+msgstr "不明な名前"
+
+msgid "Unknown country"
+msgstr "不明な国名"
+
+msgid "Click to enable"
+msgstr "enableをクリック"
+
+msgid "Click to disable"
+msgstr "disableをチェック"
+
+msgid "Installation"
+msgstr "インストレーション"
+
+msgid "Jappix installation"
+msgstr "Jappixのインストール"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Jappixのインストールへようこそ!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "このツールはJappixのインストールをサポートします。フル機能のXMPPソーシャルプラットフォームサーバがあれば、技術的な知識は必要ありません"
+
+msgid "Let's have a look at the installation steps:"
+msgstr "インストールのステップ:"
+
+msgid "Welcome"
+msgstr "ようこそ"
+
+msgid "Storage configuration"
+msgstr "ストレージの設定"
+
+msgid "Administrator account"
+msgstr "管理者アカウント"
+
+msgid "Main configuration"
+msgstr "メイン設定"
+
+msgid "Hosts configuration"
+msgstr "ホストの設定"
+
+msgid "Services installation"
+msgstr "サービスのインストール"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "もし現在の言語があなたの環境(%1s)と異なる場合、Jappixスピーク %2s を作成し保存してください。"
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Jappixのインストールや設定のヘルプが必要な場合には、全体ドキュメントを利用する事が可能です:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "個人的なソーシャルクラウドを作成するには、次のステップに移動します!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappixのデータ(共有ファイル、チャットログ、音楽、設定等)は、セキュリティで保護されたフォルダに保存します。"
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "サブフォルダを書き込む権限が必要です。%1sに権限を与えるか%2sに権限を与えてください"
+
+msgid "The folder is writable, you can continue!"
+msgstr "フォルダは書き込み可能です。続けてください。"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappixは、設定ファイル、新しいプラグイン、アップデートを提供できます。管理者権限でのアクセスが必要です。"
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Jappixのインストールが終了しました。マネジャーリンクをクリックしてホームページにアクセスしてください。"
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "パスワードが一致しません"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappixが動作するように設定する必要があります。次の項目を入力してください(通常は規定値で十分です)"
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "値を入力しない場合には、自動的に規定値が設定されます。"
+
+msgid "User"
+msgstr "ユーザー"
+
+msgid "Service"
+msgstr "サービス"
+
+msgid "Service name"
+msgstr "サービス名"
+
+msgid "Service description"
+msgstr "サービスの説明"
+
+msgid "Connection"
+msgstr "コネクション"
+
+msgid "Lock the host"
+msgstr "ホストがロックされました。"
+
+msgid "Anonymous mode"
+msgstr "匿名モード"
+
+msgid "Registration allowed"
+msgstr "承認許可"
+
+msgid "Use a proxy"
+msgstr "プロキシーを使用する"
+
+msgid "Encryption"
+msgstr "暗号化"
+
+msgid "HTTPS storage"
+msgstr "HTTPSストレージ"
+
+msgid "Force HTTPS"
+msgstr "HTTPSを強制的に使用する"
+
+msgid "Compression"
+msgstr "圧縮"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "このページでJappixが接続するホストが設定できます。オフィシャルサービスの場合はそのまま続行してください。"
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "不明なBOSHサーバです。JappixクライアントとXMPPサーバ間の接続に技術的な制限が必要です。"
+
+msgid "Main host"
+msgstr "メインホスト"
+
+msgid "Groupchat host"
+msgstr "グループチャットホスト"
+
+msgid "Anonymous host"
+msgstr "匿名ホスト"
+
+msgid "Directory host"
+msgstr "ホストの検索"
+
+msgid "BOSH host"
+msgstr "BOSHホスト"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Jappixを拡張するためにソフトウエアをインストールする事が出来ます。セキュリティの為規定値が変わる場合もあります。"
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "実行するにはroot権限でシェルを実行できるユーザでアクセスする必要があります。Jappixのいくつかの機能が制限される場合があります。"
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "セットアップ完了後キャッシュファイルを作成します。アプリケーションが表示されるまでボタンを押さずにお待ちください。"
+
+msgid "Thanks for using Jappix!"
+msgstr "Jappixをご利用いただきありがとうございます"
+
+msgid "Next"
+msgstr "次"
+
+msgid "Finish"
+msgstr "完了"
+
+msgid "Check again"
+msgstr "もう一度確認して下さい"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "フォルダーに書き込みができません。%sディレクトリーに書き込み権限を追加してください。"
+
+msgid "%s is installed on your system."
+msgstr "%s は、あなたのシステムにインストールされました"
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s はインストールされてません。%2sをインストールしてください"
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHPの最大アップロードサイズは十分です。"
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHPの最大アップロードサイズが不足しています。%3から%2sの間で設定してください。"
+
+msgid "Jappix manager"
+msgstr "Jappixマネージャ"
+
+msgid "Manager access"
+msgstr "マネージャへアクセス"
+
+msgid "Statistics"
+msgstr "統計情報"
+
+msgid "Hosts"
+msgstr "ホスト"
+
+msgid "Design"
+msgstr "デザイン"
+
+msgid "Repeat"
+msgstr "報告"
+
+msgid "All"
+msgstr "全て"
+
+msgid "Horizontal"
+msgstr "水平"
+
+msgid "Vertical"
+msgstr "垂直"
+
+msgid "Center"
+msgstr "中"
+
+msgid "Left"
+msgstr "左"
+
+msgid "Right"
+msgstr "右"
+
+msgid "Top"
+msgstr "上"
+
+msgid "Bottom"
+msgstr "下"
+
+msgid "Adapt"
+msgstr "適用"
+
+msgid "Color"
+msgstr "色"
+
+msgid "Users"
+msgstr "ユーザ"
+
+msgid "Updates"
+msgstr "アップデート"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "制限された領域:認証されたユーザだけがJappixノードを管理できます。"
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "管理パネルにログインするには、下記のフォームを利用してください。"
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "セキュリティを強化するにはセッションの制限時間を設け、ブラウザ終了時にログアウトします。"
+
+msgid "Credentials"
+msgstr "資格情報"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "あなたはログアウトしています。さようなら!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "管理者として認識できませんでした。資格情報を確認してください。"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Jappixで処理された統計情報です。重要な情報を見つけることができます。"
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "このツールを使用してJappixノードの設定を変更することが出来ます。"
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Jappixノードが送信するXMPPホストを変更することができます。"
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Jappixノードに保存されているすべてのファイルの管理ができます。サブフォルダを選択して編集を開始!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappixは完全にカスタマイズ可能です。右側でデザインが変更できます。"
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "イメージの形式が無効です。PNG,GIF又はJPGを使用してください"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "イメージを受信できませんでした。再受信しますか?"
+
+msgid "Your image was added to the list!"
+msgstr "イメージをリストに追加しました。"
+
+msgid "Changes saved!"
+msgstr "変更を保存しました。"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "一人又は複数のJappixノードの管理者が定義可能です。パスワードを変更する事も可能です。"
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Jappixのバージョンをチェックし、ノードをアップデートできます。英語で最新バージョン情報が表示されます。"
+
+msgid "Access statistics"
+msgstr "アクセス統計情報"
+
+msgid "Share statistics"
+msgstr "共有統計情報"
+
+msgid "Other statistics"
+msgstr "その他統計情報"
+
+msgid "January"
+msgstr "1月"
+
+msgid "February"
+msgstr "2月"
+
+msgid "March"
+msgstr "3月"
+
+msgid "April"
+msgstr "4月"
+
+msgid "May"
+msgstr "5月"
+
+msgid "June"
+msgstr "6月"
+
+msgid "July"
+msgstr "7月"
+
+msgid "August"
+msgstr "8月"
+
+msgid "September"
+msgstr "9月"
+
+msgid "October"
+msgstr "10月"
+
+msgid "November"
+msgstr "11月"
+
+msgid "December"
+msgstr "12月"
+
+msgid "Monday"
+msgstr "月曜日"
+
+msgid "Tuesday"
+msgstr "火曜日"
+
+msgid "Wednesday"
+msgstr "水曜日"
+
+msgid "Thursday"
+msgstr "木曜日"
+
+msgid "Friday"
+msgstr "金曜日"
+
+msgid "Saturday"
+msgstr "土曜日"
+
+msgid "Sunday"
+msgstr "日曜日"
+
+msgid "Total"
+msgstr "合計"
+
+msgid "Cache"
+msgstr "キャッシュ"
+
+msgid "Logs"
+msgstr "ログ"
+
+msgid "Music"
+msgstr "音楽"
+
+msgid "Backgrounds"
+msgstr "バックグランド"
+
+msgid "Share"
+msgstr "共有"
+
+msgid "Background"
+msgstr "バックグランド"
+
+msgid "Notice"
+msgstr "お知らせ"
+
+msgid "Your design preferences have been saved!"
+msgstr "デザイン環境設定を保存しました!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "入力項目を確認してください:何かが不足しています。"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Jappixの背景を好みの色やアップロードしたイメージに変更することができます。あなたの感性に合わせてください!"
+
+msgid "Use default background"
+msgstr "デフォルトでバックグランドを利用する"
+
+msgid "Use your own image"
+msgstr "所有しているイメージを使用する。"
+
+msgid "Select a background to use and change the display options."
+msgstr "バックグランドを選択し、ディスプレイモードを変更してください"
+
+msgid "Use your own color"
+msgstr "独自の色を使用"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "背景で使用したい色を16進数で入力してください"
+
+msgid "Manage backgrounds"
+msgstr "背景の管理"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "新しい背景を追加する事ができます。有効なイメージをアップロードしてください。"
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "背景を削除したい場合には、以下のブラウザを使用してください。"
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "全てのユーザに対しての注意書きや広告が定義できます。"
+
+msgid "Simple notice"
+msgstr "簡単なお知らせ"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "注意はテキストで表示できます。コードはサポートされていません。"
+
+msgid "Advanced notice"
+msgstr "高度な通知"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "注意をHTML,CSS、JavaScript形式にカスタマイズできます。コード形式にする必要があります。"
+
+msgid "Available updates"
+msgstr "アップデートが利用できます。"
+
+msgid "What's new?"
+msgstr "What's new?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "ストレージフォルダに書き込みがせきません。書き込みを許可してください!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s の原因はプロキシーです。%2s に増加するか、最大値 %3s にしてください。"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "開発バージョンのJappixを使用しています。%s を実行してリポジトリを更新してください。"
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "新しいバージョンのJappixがあります。確認してアップデートしてください。"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "期限切れのバージョンです。ここをクリックして%sにバージョンアップしてください。"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "バージョンは最新のようです。バージョンを手動でチェックする場合にはクリックしてください。"
+
+msgid "Check for updates"
+msgstr "アップデートをクリックしてください"
+
+msgid "Update in progress"
+msgstr "アップデートが完了しました。"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappixをアップデートしています:最新バージョンで動作しています。"
+
+msgid "The update has failed! Please try again later."
+msgstr "アップデートに失敗しました!再度試してください。"
+
+msgid "Downloading package..."
+msgstr "パッケージをダウンロード中..."
+
+msgid "Removing current Jappix system files..."
+msgstr "現在のJappixシステムファイルを削除しています。"
+
+msgid "Extracting package..."
+msgstr "パッケージを抽出中..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "ストレージフォルダツリーを再構成中..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappixをアップデートしました!"
+
+msgid "Aborted: socket error!"
+msgstr "中止:ソケットエラー"
+
+msgid "Aborted: buffer error!"
+msgstr "中止:バッファーエラー"
+
+msgid "Aborted: everything is not writable!"
+msgstr "中止:全て書き込み権がありません。"
+
+msgid "Aborted: could not extract the package!"
+msgstr "中止:パッケージを抽出することができませんでした。"
+
+msgid "Visits"
+msgstr "訪問"
+
+msgid "Daily"
+msgstr "日"
+
+msgid "Weekly"
+msgstr "週"
+
+msgid "Monthly"
+msgstr "月"
+
+msgid "Yearly"
+msgstr "年"
+
+msgid "Size"
+msgstr "サイズ"
+
+msgid "Clean everything"
+msgstr "全てをクリア"
+
+msgid "Purge cache"
+msgstr "キャッシュをパージ"
+
+msgid "Purge logs"
+msgstr "ログをパージ"
+
+msgid "Purge updates"
+msgstr "アップデートをパージ"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "ストレージフォルダを空にしました!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Jappixノードの快適さを維持するために、定期的にストレージフォルダをきれいにしてください!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Jappixに音楽(Ogg Vorbis, MP3 または WAV 形式)をアップロードして聞くことができます!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "アップロードするファイルは%sより小さくする必要があります。"
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "ユーザストアの保持期間を調整したり、望ましくないコンテンツを削除できます。"
+
+msgid "Title"
+msgstr "タイトル"
+
+msgid "Artist"
+msgstr "アーティスト"
+
+msgid "Album"
+msgstr "アルバム"
+
+msgid "File"
+msgstr "ファイル"
+
+msgid "Upload"
+msgstr "アップロード"
+
+msgid "The folder is empty."
+msgstr "フォルダは空です。"
+
+msgid "The music could not be received, please retry!"
+msgstr "音楽を受信することができませんでした。再受信してください。"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "音楽ファイルが有効ではありません。エンコードはOgg Vorbis, MP3又はWAVを使用してください!"
+
+msgid "Your music has been added!"
+msgstr "音楽を追加しました"
+
+msgid "The selected elements have been removed."
+msgstr "選択された要素は削除しました。"
+
+msgid "You must select elements to remove!"
+msgstr "削除する要素を選択する必要があります。"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "新しいユーザを追加したりパスワードの変更ができます。複雑なパスワードを設定してください!"
+
+msgid "Manage"
+msgstr "管理"
+
+msgid "List"
+msgstr "リスト"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "ユーザの削除ができます。但し、登録されているユーザが1人の場合には削除できません。"
+
+msgid "The user has been added!"
+msgstr "ユーザを追加しました。"
+
+msgid "The chosen users have been removed."
+msgstr "選択したユーザを削除しました。"
+
+msgid "You must select one or more users to be removed!"
+msgstr "削除するには1つまたは複数のユーザを選択する必要があります。"
+
+msgid "Yesterday"
+msgstr "昨日"
+
+msgid "%s days ago"
+msgstr "%s 日前"
+
+msgid "User currently active"
+msgstr "ユーザは現在アクティブです。"
+
+msgid "Last seen: %s"
+msgstr "最終確認: %s"
+
+msgid "Inactive since: %s"
+msgstr "%s からアクティブでない"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "友達はメッセージを返信することができません!"
+
+msgid "Static content server"
+msgstr "スタティックコンテンツサーバ"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "“%2s” %1s はスタティックコンテンツサーバです。"
+
+msgid "Suggested friends"
+msgstr "友達の申請"
+
+msgid "Check all"
+msgstr "全てをチェック"
+
+msgid "Uncheck all"
+msgstr "全てのチェックの解除"
+
+msgid "Choose"
+msgstr "選択"
+
+msgid "List name"
+msgstr "苗字"
+
+msgid "Allow"
+msgstr "許可"
+
+msgid "Deny"
+msgstr "不許可"
+
+msgid "Group"
+msgstr "グループ"
+
+msgid "Subscription"
+msgstr "サブスクリプション"
+
+msgid "Both"
+msgstr "両方"
+
+msgid "From"
+msgstr "から"
+
+msgid "Everybody"
+msgstr "みんな"
+
+msgid "Send messages"
+msgstr "メッセージ送信"
+
+msgid "Send queries"
+msgstr "クエリー送信"
+
+msgid "See my status"
+msgstr "自分のステータスを見る"
+
+msgid "Send his/her status"
+msgstr "彼/彼女にステータスを送る"
+
+msgid "Everything"
+msgstr "全部"
+
+msgid "Item"
+msgstr "アイテム"
+
+msgid "Order"
+msgstr "その他"
+
+msgid "Active for this session"
+msgstr "セッションがアクティブになりました"
+
+msgid "Always active"
+msgstr "常にアクティブ"
+
+msgid "User directory"
+msgstr "ユーザーディレクトリ"
+
+msgid "Search a friend"
+msgstr "友達を検索"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "要求されたリクエストは、受信者又はサーバに実装されていないため、処理する事ができません"
+
+msgid "This is a repeat from %s"
+msgstr "%sからのレポート"
+
+msgid "Loading comments..."
+msgstr "コメントをロード中…"
+
+msgid "Type your comment here..."
+msgstr "ここにコメントを入力してください…"
+
+msgid "Could not get the comments!"
+msgstr "コメントを取得できませんでした。"
+
+msgid "Show comments"
+msgstr "コメントを見る"
+
+msgid "Send him/her a message"
+msgstr "彼/彼女にメッセージを送る"
+
+msgid "Start a chat with him/her"
+msgstr "彼/彼女とチャットする"
+
+msgid "Media integration"
+msgstr "メディア統合"
+
+msgid "Comments locked!"
+msgstr "コメントがロックされています"
+
+msgid "Type something you want to share with your friends..."
+msgstr "友達と共有したいものを入力…"
+
+msgid "changed his/her nickname to %s"
+msgstr "彼/彼女のニックネームを %s に変更"
+
+msgid "commented an item you follow: “%s”."
+msgstr "“%s”のコメントをフォローする"
+
+msgid "Hide"
+msgstr "隠す"
+
+msgid "liked your post: “%s”."
+msgstr "“%s”にいいねを送信する"
+
+msgid "quoted you somewhere: “%s”."
+msgstr "“%s”を引用する"
+
+msgid "published on your wall: “%s”."
+msgstr "“%s”を公開する。"
+
+msgid "tagged you in a photo (%s)."
+msgstr "写真(%s)にタグを付けました。"
+
+msgid "tagged you in a video (%s)."
+msgstr "映像(%s)にタグを付けました。"
+
+msgid "Show"
+msgstr "見る"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "ヘルプが必要ですか?ドキュメントページをよく読むか、このフォームを入力してください!"
+
+msgid "Pubsub host"
+msgstr "Pubsubホスト"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappixは素晴らしいソーシャルプラットフォームです。どこにいてもいつでもアクセスできます。"
+
+msgid "Manager link"
+msgstr "マネージャーリンク"
+
+msgid "User uploads server"
+msgstr "ユーザアップロードサーバ"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "“%2s”を%1sサーバにアップロードしました。"
+
+msgid "Logo"
+msgstr "ロゴ"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "デフォルトからあなたのサービスロゴに変更する事が出来ます。サイズと色に気をつけて!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "推奨されるピクセルサイズのロゴをアップロードできます"
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "有効なイメージではありません。PNGフォーマットを使用してください。"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "サービスロゴを変更しました。"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "ロゴフォーマットはPNG形式を使用する必要があります。フィールドが空欄の場合はロゴは変更されません。"
+
+msgid "Remove this logo"
+msgstr "このロゴの削除"
+
+msgid "View this logo"
+msgstr "このロゴを見る"
+
+msgid "Send a file"
+msgstr "ファイル送信"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "アップロードとは、友達が望むダウンロードファイルを送ることです。"
+
+msgid "Groupchats to join"
+msgstr "画像結合"
+
+msgid "Purge sent files"
+msgstr "送信ファイルのパージ"
+
+msgid "would like to send you a file: “%s”."
+msgstr "送信ファイルは“%s”のようになります"
+
+msgid "has accepted to received your file: “%s”."
+msgstr "“%s”ファイルを受信する事を受け入れました。"
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "“%s”ファイルの受け取りを拒否しました。"
+
+msgid "could not receive your file: “%s”."
+msgstr "“%s”ファイルを受け取ることができません。"
+
+msgid "has received a file exchange request: “%s”."
+msgstr "“%s”ファイル交換要求を受信しました。"
+
+msgid "Available shortcuts:"
+msgstr "使用可能なショートカット:"
+
+msgid "%s removes the chat logs"
+msgstr "%s はチャットログを削除しました。"
+
+msgid "%s joins a groupchat"
+msgstr "%s はグループチャットに接続しました。"
+
+msgid "%s closes the chat"
+msgstr "%s はチャットをクローズしました。"
+
+msgid "%s shows the user profile"
+msgstr "%s のユーザプロファイルを見る。"
+
+msgid "%s sends a message to the room"
+msgstr "%s は部屋にメッセージを送信する。"
+
+msgid "%s changes your nickname"
+msgstr "%s はニックネームを変更しました。"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s は部屋の誰かにメッセージを送ります。"
+
+msgid "%s changes the room topic"
+msgstr "%s は部屋のトピックを変更しました。"
+
+msgid "%s kicks an user of the room"
+msgstr "%s を部屋から追い出しました。"
+
+msgid "%s bans an user of the room"
+msgstr "%s の部屋の使用を禁止しました。"
+
+msgid "%s invites someone to join the room"
+msgstr "%s は部屋の出席者を招待しています。"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappixは非営利のソーシャルプラットフォームです。どこにいてもアクセスでき、いつでもコミュニケーションを取ることができます。"
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/nl/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/nl/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..a0e272c
Binary files /dev/null and b/jappixmini/jappix/lang/nl/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/nl/LC_MESSAGES/main.po b/jappixmini/jappix/lang/nl/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..e85c315
--- /dev/null
@@ -0,0 +1,1870 @@
+# Dutch translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr ""
+
+msgid "An open social network"
+msgstr ""
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix is onderbroken door een netwerk probleem, een fout of een slechte login (controleer dat je de juiste gegevens hebt ingegeven), sorry voor het ongemak."
+
+msgid "The element list on this server could not be obtained!"
+msgstr ""
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Uw paswoord is gewijzigd, U kan nu aanmelden met de nieuwe gegevens."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr ""
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr ""
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "De kamer die je binnenkwam bestaat nog niet. Je moet ze eerst aanmaken!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Het groepsgesprek is verwijderd. Nu kan iemand anders ze opnieuw aanmaken."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr ""
+
+msgid "Please enter the group chat address to join."
+msgstr ""
+
+msgid "Please enter your nickname to join %s."
+msgstr ""
+
+msgid "This room (%s) is protected with a password."
+msgstr ""
+
+msgid "Your browser is out of date!"
+msgstr ""
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr "Log in"
+
+msgid "Register"
+msgstr "Registreer"
+
+msgid "Here we go!"
+msgstr "Hier gaan we dan!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Paswoord"
+
+msgid "Remember me"
+msgstr "Herinner mij"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr ""
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr ""
+
+msgid "Reconnect"
+msgstr ""
+
+msgid "Messages"
+msgstr "Berichten"
+
+msgid "Profile"
+msgstr "Profiel"
+
+msgid "Options"
+msgstr "Opties"
+
+msgid "Disconnect"
+msgstr "Verbreek de verbinding"
+
+msgid "Filter"
+msgstr ""
+
+msgid "Add a friend"
+msgstr ""
+
+msgid "Your groupchats"
+msgstr ""
+
+msgid "Manage your favorite groupchats"
+msgstr "Beheer je favoriete groepsgesprekken"
+
+msgid "More stuff"
+msgstr ""
+
+msgid "Show all friends"
+msgstr "Toon alle vrienden"
+
+msgid "Only show connected friends"
+msgstr ""
+
+msgid "Message archives"
+msgstr "Berichten archief"
+
+msgid "Date"
+msgstr "Datum"
+
+msgid "Please select a friend to view the chat history."
+msgstr ""
+
+msgid "Nothing found for: %s"
+msgstr ""
+
+msgid "A short message?"
+msgstr "Een kort bericht?"
+
+msgid "How are you?"
+msgstr "Hoe gaat het ermee?"
+
+msgid "What are you doing?"
+msgstr "Wat ben je aan het doen?"
+
+msgid "Join a chat"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Available"
+msgstr "Beschikbaar"
+
+msgid "Talkative"
+msgstr "Spraakzaam"
+
+msgid "Away"
+msgstr "Weg"
+
+msgid "Not available"
+msgstr "Niet beschikbaar"
+
+msgid "Busy"
+msgstr "Bezig"
+
+msgid "Mood"
+msgstr ""
+
+msgid "None"
+msgstr "Geen"
+
+msgid "Crazy"
+msgstr "Gek"
+
+msgid "Excited"
+msgstr "Opgewonden"
+
+msgid "Playful"
+msgstr "Speels"
+
+msgid "Happy"
+msgstr "Vrolijk"
+
+msgid "Shocked"
+msgstr "Geschokt"
+
+msgid "Hot"
+msgstr "Vurig"
+
+msgid "Sad"
+msgstr "Triest"
+
+msgid "Amorous"
+msgstr "Verliefd"
+
+msgid "Confident"
+msgstr "Zelfverzekerd"
+
+msgid "Activity"
+msgstr ""
+
+msgid "Chores"
+msgstr ""
+
+msgid "Drinking"
+msgstr "Drinken"
+
+msgid "Eating"
+msgstr "Eten"
+
+msgid "Exercising"
+msgstr ""
+
+msgid "Grooming"
+msgstr ""
+
+msgid "Appointment"
+msgstr "Afspraak"
+
+msgid "Inactive"
+msgstr "Inactief"
+
+msgid "Relaxing"
+msgstr "Uitrusten"
+
+msgid "Talking"
+msgstr "Praten"
+
+msgid "Traveling"
+msgstr "Reizen"
+
+msgid "Working"
+msgstr "Werken"
+
+msgid "View profile"
+msgstr ""
+
+msgid "Repeat this notice"
+msgstr "Herhaal deze melding"
+
+msgid "Remove this notice"
+msgstr "Verwijder deze melding"
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Identity"
+msgstr "Identiteit"
+
+msgid "Profile image"
+msgstr ""
+
+msgid "Others"
+msgstr ""
+
+msgid "Personal"
+msgstr ""
+
+msgid "Complete name"
+msgstr "Volledige naam"
+
+msgid "Nickname"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Date of birth"
+msgstr ""
+
+msgid "Contact"
+msgstr "Contact"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr ""
+
+msgid "Website"
+msgstr "Website"
+
+msgid "Current"
+msgstr ""
+
+msgid "Delete"
+msgstr "Verwijder"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr ""
+
+msgid "Address"
+msgstr ""
+
+msgid "Street"
+msgstr "Straat"
+
+msgid "City"
+msgstr "Stad"
+
+msgid "Postal code"
+msgstr "Postcode"
+
+msgid "Country"
+msgstr "Land"
+
+msgid "Biography"
+msgstr "Biografie"
+
+msgid "Important notice"
+msgstr "Belangrijke mededeling"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr ""
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr ""
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "Opslaan"
+
+msgid "Cancel"
+msgstr "Annuleren"
+
+msgid "Edit options"
+msgstr ""
+
+msgid "Channel"
+msgstr ""
+
+msgid "Commands"
+msgstr ""
+
+msgid "Sounds"
+msgstr "Geluiden"
+
+msgid "Privacy"
+msgstr "Privacy"
+
+msgid "Message archiving"
+msgstr "Bericht archivering"
+
+msgid "Store a history of your chats"
+msgstr ""
+
+msgid "Geolocation"
+msgstr "Geolocatie"
+
+msgid "Empty"
+msgstr "Leeg"
+
+msgid "Empty channel"
+msgstr ""
+
+msgid "Persistent"
+msgstr "Blijvend"
+
+msgid "Maximum notices"
+msgstr "Maximale meldingen"
+
+msgid "Account"
+msgstr ""
+
+msgid "Change password"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Old"
+msgstr "Oud"
+
+msgid "New (2 times)"
+msgstr "Nieuw (2 keer)"
+
+msgid "Continue"
+msgstr ""
+
+msgid "To"
+msgstr "Naar"
+
+msgid "Close"
+msgstr "Sluiten"
+
+msgid "unknown"
+msgstr "onbekend"
+
+msgid "Unavailable"
+msgstr "Niet beschikbaar"
+
+msgid "is now"
+msgstr ""
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr ""
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr ""
+
+msgid "The image file is not supported or has a bad size."
+msgstr ""
+
+msgid "Reply"
+msgstr "Antwoord"
+
+msgid "Error"
+msgstr "Fout"
+
+msgid "Click here to solve the error"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "Remove"
+msgstr "Verwijder"
+
+msgid "Rename"
+msgstr "Hernoem"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr ""
+
+msgid "Smiley insertion"
+msgstr "Emoticon invoegen"
+
+msgid "Change style"
+msgstr ""
+
+msgid "Text in bold"
+msgstr "Tekst vetgedrukt"
+
+msgid "Text in italic"
+msgstr "Tekst schuin"
+
+msgid "Underlined text"
+msgstr "Tekst onderstreept"
+
+msgid "Save chat"
+msgstr ""
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr ""
+
+msgid "This chat is empty!"
+msgstr ""
+
+msgid "Generate file!"
+msgstr ""
+
+msgid "Download file!"
+msgstr ""
+
+msgid "Clean current chat"
+msgstr ""
+
+msgid "View chat history"
+msgstr ""
+
+msgid "Show user profile"
+msgstr ""
+
+msgid "Add this contact to your friends"
+msgstr ""
+
+msgid "Add this groupchat to your favorites"
+msgstr ""
+
+msgid "All tabs"
+msgstr ""
+
+msgid "Close this tab"
+msgstr ""
+
+msgid "no subject defined for this room."
+msgstr "Deze kamer heeft geen onderwerp"
+
+msgid "Administration panel for this room"
+msgstr ""
+
+msgid "Moderators"
+msgstr ""
+
+msgid "Participants"
+msgstr "Deelnemers"
+
+msgid "Visitors"
+msgstr "Bezoekers"
+
+msgid "Manage favorite rooms"
+msgstr ""
+
+msgid "Change favorites"
+msgstr ""
+
+msgid "Search a room"
+msgstr "Zoek een kamer"
+
+msgid "Select a favorite"
+msgstr ""
+
+msgid "Getting the name..."
+msgstr ""
+
+msgid "Gateway"
+msgstr ""
+
+msgid "Name"
+msgstr "Naam"
+
+msgid "Room"
+msgstr "Kamer"
+
+msgid "Add"
+msgstr "Voeg toe"
+
+msgid "Edit"
+msgstr "Wijzig"
+
+msgid "Search a room on"
+msgstr ""
+
+msgid "No room found on this server."
+msgstr "Geen kamer gevonden op deze server"
+
+msgid "Service discovery"
+msgstr ""
+
+msgid "Server to query"
+msgstr ""
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr ""
+
+msgid "Authentications"
+msgstr ""
+
+msgid "Automation"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Collaboration"
+msgstr "Samenwerking"
+
+msgid "Components"
+msgstr ""
+
+msgid "Rooms"
+msgstr "Kamers"
+
+msgid "Directories"
+msgstr ""
+
+msgid "Gateways"
+msgstr ""
+
+msgid "News"
+msgstr "Nieuws"
+
+msgid "Hierarchy"
+msgstr "Hiërarchie"
+
+msgid "Proxies"
+msgstr ""
+
+msgid "Publication/Subscription"
+msgstr ""
+
+msgid "Storage"
+msgstr "Opslag"
+
+msgid "Service offline or broken"
+msgstr ""
+
+msgid "Your inbox"
+msgstr ""
+
+msgid "Available actions"
+msgstr "Beschikabre acties"
+
+msgid "Clean"
+msgstr ""
+
+msgid "New"
+msgstr "Nieuw"
+
+msgid "Received"
+msgstr "Ontvangen"
+
+msgid "Subject"
+msgstr "Onderwerp"
+
+msgid "Content"
+msgstr "Inhoud"
+
+msgid "Send message"
+msgstr ""
+
+msgid "Your inbox is empty."
+msgstr ""
+
+msgid "MUC administration"
+msgstr "MUC beheer"
+
+msgid "You administrate this room"
+msgstr ""
+
+msgid "Enter new subject"
+msgstr ""
+
+msgid "Configuration"
+msgstr "Configuratie"
+
+msgid "Authorizations"
+msgstr ""
+
+msgid "Member list"
+msgstr ""
+
+msgid "Owner list"
+msgstr ""
+
+msgid "Administrator list"
+msgstr ""
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr "Verwijder deze MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Ja, laten we het doen!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr ""
+
+msgid "Your friend is writing a message..."
+msgstr "Je vriend schrijft een bericht..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Je vriend is gestopt met het schrijven van een bericht."
+
+msgid "Your friend is doing something else."
+msgstr "Je vriend is wat anders aan het doen."
+
+msgid "Your friend closed the chat."
+msgstr ""
+
+msgid "Requesting this service..."
+msgstr ""
+
+msgid "Loading"
+msgstr "Laden"
+
+msgid "joined the chat room"
+msgstr ""
+
+msgid "left the chat room"
+msgstr ""
+
+msgid "no status"
+msgstr ""
+
+msgid "has been kicked"
+msgstr ""
+
+msgid "has been banned"
+msgstr ""
+
+msgid "no reason"
+msgstr ""
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr "Hallo!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr ""
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr "Vorige"
+
+msgid "General"
+msgstr "Algemeen"
+
+msgid "Advanced"
+msgstr "Geavanceerd"
+
+msgid "Resource"
+msgstr ""
+
+msgid "Priority"
+msgstr "Prioriteit"
+
+msgid "Low"
+msgstr "Laag"
+
+msgid "Medium"
+msgstr "Middelmatig"
+
+msgid "High"
+msgstr "Hoog"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr "Login pagina"
+
+msgid "Share this link with your friends:"
+msgstr "Deel deze link met je vrienden:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr "Verplicht"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Je bent geregistreerd, hier is je XMPP adres:"
+
+msgid "Manager"
+msgstr "Manager"
+
+msgid "Project"
+msgstr "Project"
+
+msgid "Encrypted"
+msgstr "Versleuteld"
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr "Waar ben je?"
+
+msgid "What's up with you?"
+msgstr "Hoe gaat het met je?"
+
+msgid "Fetching the social channel..."
+msgstr "Binnenhalen van het kanaal..."
+
+msgid "You are synchronized with your network."
+msgstr "Je bent gesynchroniseerd met het netwerk"
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Kan niets verzenden: je kunt alleen berichten ontvangen!"
+
+msgid "Media viewer"
+msgstr ""
+
+msgid "Browse"
+msgstr "Blader"
+
+msgid "Command"
+msgstr "Commando"
+
+msgid "Subscribe"
+msgstr "Inschrijven"
+
+msgid "Join"
+msgstr "Aanmelden"
+
+msgid "Automatic"
+msgstr "Automatisch"
+
+msgid "Search"
+msgstr "Zoek"
+
+msgid "No result!"
+msgstr "Geen resultaat!"
+
+msgid "No notifications."
+msgstr "Geen meldingen"
+
+msgid "would like to add you as a friend."
+msgstr "zou je graag als vriend toevoegen."
+
+msgid "would like you to join this chatroom:"
+msgstr "wil naar je chatroom komen."
+
+msgid "Do you accept?"
+msgstr "Ben je het ermee eens?"
+
+msgid "Yes"
+msgstr "Ja"
+
+msgid "No"
+msgstr "Nee"
+
+msgid "would like to get authorization."
+msgstr "wil geauthoriseerd worden."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr "Verzend"
+
+msgid "Client"
+msgstr "Client"
+
+msgid "System"
+msgstr "Systeem"
+
+msgid "Local time"
+msgstr "Lokale tijd"
+
+msgid "Comments"
+msgstr "Commentaar"
+
+msgid "User profile"
+msgstr "Gebruikers profiel"
+
+msgid "See his/her position on the globe"
+msgstr "Bekijk zijn/haar positie op de wereld"
+
+msgid "Confirm"
+msgstr "Bevestig"
+
+msgid "anonymous mode"
+msgstr "anonieme modus"
+
+msgid "Groups"
+msgstr "Groepen"
+
+msgid "Unclassified"
+msgstr "Ongeklassificeerd"
+
+msgid "Authorize"
+msgstr "Autoriseer"
+
+msgid "Ask for authorization"
+msgstr "Vraag om een authorisatie"
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Prohibit"
+msgstr "Toegestaan"
+
+msgid "Block"
+msgstr "Blokkeren"
+
+msgid "Chat"
+msgstr "Gesprek"
+
+msgid "Groupchat"
+msgstr "Groepsgesprek"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobiel"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Mobiel"
+
+msgid "Please wait..."
+msgstr "Even geduld aub ..."
+
+msgid "Please enable JavaScript"
+msgstr "Activeer Javascript"
+
+msgid "Your channel"
+msgstr "Jouw kanaal"
+
+msgid "Channel of"
+msgstr "Kanaal van"
+
+msgid "More notices..."
+msgstr "Meer mededelingen..."
+
+msgid "Attach a file"
+msgstr "Toevoegen van bestand"
+
+msgid "Send"
+msgstr "Verzenden"
+
+msgid "Unattach the file"
+msgstr ""
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr ""
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr ""
+
+msgid "Internal server error, try later"
+msgstr "Interne server fout, probeer het later"
+
+msgid "Your form has been sent."
+msgstr ""
+
+msgid "Application"
+msgstr "Applicatie"
+
+msgid "XMPP links"
+msgstr "XMPP links"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Open XMPP links met Jappix"
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr "Welkom!"
+
+msgid "Friends"
+msgstr "Vrienden"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr ""
+
+msgid "Don't hide offline friends"
+msgstr ""
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr "Onbekende naam"
+
+msgid "Unknown country"
+msgstr "Onbekend land"
+
+msgid "Click to enable"
+msgstr ""
+
+msgid "Click to disable"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Jappix installation"
+msgstr ""
+
+msgid "Welcome to the Jappix installation!"
+msgstr ""
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr ""
+
+msgid "Storage configuration"
+msgstr ""
+
+msgid "Administrator account"
+msgstr ""
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr ""
+
+msgid "Services installation"
+msgstr ""
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr ""
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service name"
+msgstr ""
+
+msgid "Service description"
+msgstr ""
+
+msgid "Connection"
+msgstr ""
+
+msgid "Lock the host"
+msgstr ""
+
+msgid "Anonymous mode"
+msgstr ""
+
+msgid "Registration allowed"
+msgstr ""
+
+msgid "Use a proxy"
+msgstr ""
+
+msgid "Encryption"
+msgstr ""
+
+msgid "HTTPS storage"
+msgstr ""
+
+msgid "Force HTTPS"
+msgstr ""
+
+msgid "Compression"
+msgstr ""
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr ""
+
+msgid "Groupchat host"
+msgstr ""
+
+msgid "Anonymous host"
+msgstr ""
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Finish"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr ""
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Hosts"
+msgstr ""
+
+msgid "Design"
+msgstr ""
+
+msgid "Repeat"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Horizontal"
+msgstr ""
+
+msgid "Vertical"
+msgstr ""
+
+msgid "Center"
+msgstr ""
+
+msgid "Left"
+msgstr ""
+
+msgid "Right"
+msgstr ""
+
+msgid "Top"
+msgstr ""
+
+msgid "Bottom"
+msgstr ""
+
+msgid "Adapt"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "You have been logged out. Goodbye!"
+msgstr ""
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr ""
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr ""
+
+msgid "Backgrounds"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr ""
+
+msgid "Notice"
+msgstr ""
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr ""
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr ""
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr ""
+
+msgid "Update in progress"
+msgstr ""
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr ""
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr ""
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr ""
+
+msgid "Daily"
+msgstr ""
+
+msgid "Weekly"
+msgstr ""
+
+msgid "Monthly"
+msgstr ""
+
+msgid "Yearly"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Clean everything"
+msgstr ""
+
+msgid "Purge cache"
+msgstr ""
+
+msgid "Purge logs"
+msgstr ""
+
+msgid "Purge updates"
+msgstr ""
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Artist"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "The folder is empty."
+msgstr ""
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr ""
+
+msgid "The chosen users have been removed."
+msgstr ""
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "%s days ago"
+msgstr ""
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr ""
+
+msgid "Uncheck all"
+msgstr ""
+
+msgid "Choose"
+msgstr ""
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/oc/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/oc/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..28501c4
Binary files /dev/null and b/jappixmini/jappix/lang/oc/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/oc/LC_MESSAGES/main.po b/jappixmini/jappix/lang/oc/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..1f2d628
--- /dev/null
@@ -0,0 +1,1870 @@
+# Occitan translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript es pas dins vòstre navigator, podretz pas far foncionar Jappix ! Corregís aquò, si vos plai."
+
+msgid "An open social network"
+msgstr "Un malhum sociau dubert"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix es estat arrestat per un problema de malhum, un bug o de meschants identificants (de verificar). Fasetz-nos excusa. "
+
+msgid "The element list on this server could not be obtained!"
+msgstr "La lista daus elements presents sus queu servidor es pas estada obtenguda !"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Vòstre senhau es estat chamnhat, aura vos podetz connectar a vòstre compte emb vòstres noveus identificants.   "
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Vòstre compte XMPP es estat esfaçat, au reveire !"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Setz estat desconnetat de vòstre compte XMPP, bona jornada !"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Lo charrador qu'avetz jongut existís pas. Zo podetz crear !"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Lo charrador es estat esfaçat, aura quauqu'un mai zo podrà tornar crear."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "L'utilizaire que voletz júnher es pas present dins lo charrador. "
+
+msgid "Please enter the group chat address to join."
+msgstr "Picatz l'adreça dau charrador de júnher, si vos plai."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Picatz vòstre chafre per júnher %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Lo charrador (%s) es protegit per un senhau."
+
+msgid "Your browser is out of date!"
+msgstr "Vòstre navigator es pas a jorn !"
+
+msgid "Last %s version is better!"
+msgstr "La darriera version de %s es melhor !"
+
+msgid "Login"
+msgstr "Dubrir una session"
+
+msgid "Register"
+msgstr "Se marcar"
+
+msgid "Here we go!"
+msgstr "Anem, òc !"
+
+msgid "Server"
+msgstr "Servidor"
+
+msgid "Password"
+msgstr "Senhau"
+
+msgid "Remember me"
+msgstr "Se sovenir de me"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Queu gatge es estat desactivat, lo podetz pas utilizar !"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Per causa d'un problema de malhum, setz estat desconnectat. Que voletz far aura ?"
+
+msgid "Reconnect"
+msgstr "Tornar connectar"
+
+msgid "Messages"
+msgstr "Messatges"
+
+msgid "Profile"
+msgstr "Perfil"
+
+msgid "Options"
+msgstr "Preferéncias"
+
+msgid "Disconnect"
+msgstr "Barrar la session"
+
+msgid "Filter"
+msgstr "Filtrar"
+
+msgid "Add a friend"
+msgstr "Apondre un amic"
+
+msgid "Your groupchats"
+msgstr "Vòstres charradors"
+
+msgid "Manage your favorite groupchats"
+msgstr "Gerir vòstres charradors preferits"
+
+msgid "More stuff"
+msgstr "Mai de chausas"
+
+msgid "Show all friends"
+msgstr "Mostrar tots los amics"
+
+msgid "Only show connected friends"
+msgstr "Mostrar nonmàs los amics en linha"
+
+msgid "Message archives"
+msgstr "Archius de messatges"
+
+msgid "Date"
+msgstr "Data"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Si vos plai, seleccionatz un amic per veire l'istoric de la charrada."
+
+msgid "Nothing found for: %s"
+msgstr "Se trobet pas ren per : %s"
+
+msgid "A short message?"
+msgstr "Un pitit messatge ?"
+
+msgid "How are you?"
+msgstr "Coma quò vai ?"
+
+msgid "What are you doing?"
+msgstr "Que fasetz ?"
+
+msgid "Join a chat"
+msgstr "Júnher una charrada"
+
+msgid "Status"
+msgstr "Estat"
+
+msgid "Available"
+msgstr "Disponible/a"
+
+msgid "Talkative"
+msgstr "Platussaire/a"
+
+msgid "Away"
+msgstr "Absent(a)"
+
+msgid "Not available"
+msgstr "Pas disponible"
+
+msgid "Busy"
+msgstr "Ocupat"
+
+msgid "Mood"
+msgstr "Umor"
+
+msgid "None"
+msgstr "Pas ren"
+
+msgid "Crazy"
+msgstr "Franc fadard(a)"
+
+msgid "Excited"
+msgstr "Excitat/ada"
+
+msgid "Playful"
+msgstr "Joiós/osa"
+
+msgid "Happy"
+msgstr "Aürós/osa"
+
+msgid "Shocked"
+msgstr "Impressionat/ada"
+
+msgid "Hot"
+msgstr "Chaud(a)"
+
+msgid "Sad"
+msgstr "Triste/a"
+
+msgid "Amorous"
+msgstr "Amorós/osa"
+
+msgid "Confident"
+msgstr "Fisançós/osa"
+
+msgid "Activity"
+msgstr "Activitat"
+
+msgid "Chores"
+msgstr "Corvadas"
+
+msgid "Drinking"
+msgstr "Beu"
+
+msgid "Eating"
+msgstr "Minja"
+
+msgid "Exercising"
+msgstr "Entraïnament"
+
+msgid "Grooming"
+msgstr "Se toaleta"
+
+msgid "Appointment"
+msgstr "Rendez-vos"
+
+msgid "Inactive"
+msgstr "Inactiu/iva"
+
+msgid "Relaxing"
+msgstr "Banturla"
+
+msgid "Talking"
+msgstr "Platussa"
+
+msgid "Traveling"
+msgstr "En viatge"
+
+msgid "Working"
+msgstr "Trabalha"
+
+msgid "View profile"
+msgstr "Veire lo perfil"
+
+msgid "Repeat this notice"
+msgstr "Repetir quel avís "
+
+msgid "Remove this notice"
+msgstr "Esfaçar quel avís "
+
+msgid "Your profile"
+msgstr "Vòstre perfil"
+
+msgid "Identity"
+msgstr "Identitat"
+
+msgid "Profile image"
+msgstr "Imatge de perfil"
+
+msgid "Others"
+msgstr "Autres"
+
+msgid "Personal"
+msgstr "Personau"
+
+msgid "Complete name"
+msgstr "Nom complet"
+
+msgid "Nickname"
+msgstr "Chafre"
+
+msgid "First name"
+msgstr "Pitit nom"
+
+msgid "Last name"
+msgstr "Nom"
+
+msgid "Date of birth"
+msgstr "Data de naissença"
+
+msgid "Contact"
+msgstr "Contacte"
+
+msgid "E-mail"
+msgstr "Adreça electronica"
+
+msgid "Phone"
+msgstr "Telefòn"
+
+msgid "Website"
+msgstr "Sit web"
+
+msgid "Current"
+msgstr "Actuau"
+
+msgid "Delete"
+msgstr "Suprimir"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "De que ? Avetz pas d'imatge de perfil definida sus vòstra carta d'identitat !"
+
+msgid "Address"
+msgstr "Adreça"
+
+msgid "Street"
+msgstr "Rua"
+
+msgid "City"
+msgstr "Vila"
+
+msgid "Postal code"
+msgstr "Còdi postau"
+
+msgid "Country"
+msgstr "País"
+
+msgid "Biography"
+msgstr "Biografia"
+
+msgid "Important notice"
+msgstr "Important"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Siatz prudents emb las informacions qu'escrivetz sus vòstre perfil. Son accesiblas a tot lo monde quitament a los que voletz pas."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Tot es pas privat sus XMPP, per exemple vòstre perfil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Qu'es recomandat de charjar un imatge de perfil (%s maximum), coma una fòto de vosautres, per que vòstres amics vos pueschan conéisser."
+
+msgid "Save"
+msgstr "Sauvar"
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Edit options"
+msgstr "Editar las opcions"
+
+msgid "Channel"
+msgstr "Canau"
+
+msgid "Commands"
+msgstr "Òrdres"
+
+msgid "Sounds"
+msgstr "Sons"
+
+msgid "Privacy"
+msgstr "Vita privada"
+
+msgid "Message archiving"
+msgstr "Archivatge daus messatges"
+
+msgid "Store a history of your chats"
+msgstr "Gardar un istoric de vòstras charradas"
+
+msgid "Geolocation"
+msgstr "Geolocalizacion"
+
+msgid "Empty"
+msgstr "Voidar"
+
+msgid "Empty channel"
+msgstr "Voidar lo canau"
+
+msgid "Persistent"
+msgstr "Persistent"
+
+msgid "Maximum notices"
+msgstr "Maximum d'avís"
+
+msgid "Account"
+msgstr "Compte"
+
+msgid "Change password"
+msgstr "Chamnhar de senhau"
+
+msgid "Delete account"
+msgstr "Suprimir lo compte"
+
+msgid "Old"
+msgstr "Ancian"
+
+msgid "New (2 times)"
+msgstr "Nuòu (2 còps)"
+
+msgid "Continue"
+msgstr "Contunhar"
+
+msgid "To"
+msgstr "A"
+
+msgid "Close"
+msgstr "Barrar"
+
+msgid "unknown"
+msgstr "inconegut/uda"
+
+msgid "Unavailable"
+msgstr "Desconnectat/ada"
+
+msgid "is now"
+msgstr "es aura"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Esperatz dau temps que vòstre avatar se charja..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Veiquí ! Un brave imatge de perfil tot nuòu !"
+
+msgid "The image file is not supported or has a bad size."
+msgstr ""
+
+msgid "Reply"
+msgstr "Respondre"
+
+msgid "Error"
+msgstr "Error"
+
+msgid "Click here to solve the error"
+msgstr "Clicar aicí per corregir l'error"
+
+msgid "You"
+msgstr "Vosautres/as"
+
+msgid "Remove"
+msgstr ""
+
+msgid "Rename"
+msgstr "Renomenar "
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Adiu ! Sei %s, vos voldriá apondre coma amic."
+
+msgid "Smiley insertion"
+msgstr "Insercion d'emoticòna"
+
+msgid "Change style"
+msgstr "Chamnhar l'aparéncia"
+
+msgid "Text in bold"
+msgstr "Texte en gras"
+
+msgid "Text in italic"
+msgstr "Texte en italic"
+
+msgid "Underlined text"
+msgstr "Texte joslinhat"
+
+msgid "Save chat"
+msgstr "Enregistrar la charrada"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Clicatz sus lo liam per aver l'istoric de la charrada. Puei tornatz clicar per lo recuperar."
+
+msgid "This chat is empty!"
+msgstr "Quela charrada es voida !"
+
+msgid "Generate file!"
+msgstr "Generar lo fichier !"
+
+msgid "Download file!"
+msgstr "Descharjar lo fichier !"
+
+msgid "Clean current chat"
+msgstr "Netiar la charrada "
+
+msgid "View chat history"
+msgstr "Veire l'istoric de la charrada"
+
+msgid "Show user profile"
+msgstr "Mostrar lo perfil de l'utilizaire"
+
+msgid "Add this contact to your friends"
+msgstr "Apondre queu contacte a vòstres amics"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Apondre queu charrador a vòstres preferits"
+
+msgid "All tabs"
+msgstr "Tots los onglets"
+
+msgid "Close this tab"
+msgstr "Barrar quel onglet"
+
+msgid "no subject defined for this room."
+msgstr "p'un subjècte definit per queu charrador."
+
+msgid "Administration panel for this room"
+msgstr ""
+
+msgid "Moderators"
+msgstr "Moderador(a)s"
+
+msgid "Participants"
+msgstr "Participant(a)s"
+
+msgid "Visitors"
+msgstr "Visitaires/as"
+
+msgid "Manage favorite rooms"
+msgstr "Gerir los charradors preferits"
+
+msgid "Change favorites"
+msgstr "Modificar los preferits"
+
+msgid "Search a room"
+msgstr "Cerchar un charrador"
+
+msgid "Select a favorite"
+msgstr "Seleccionatz un preferit"
+
+msgid "Getting the name..."
+msgstr "Obtencion dau nom..."
+
+msgid "Gateway"
+msgstr "Passarèla"
+
+msgid "Name"
+msgstr "Nom"
+
+msgid "Room"
+msgstr "Charrador"
+
+msgid "Add"
+msgstr "Apondre"
+
+msgid "Edit"
+msgstr "Editar"
+
+msgid "Search a room on"
+msgstr ""
+
+msgid "No room found on this server."
+msgstr ""
+
+msgid "Service discovery"
+msgstr ""
+
+msgid "Server to query"
+msgstr ""
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr "Comptes"
+
+msgid "Authentications"
+msgstr "Autentificacion   "
+
+msgid "Automation"
+msgstr "Automatizacion"
+
+msgid "Clients"
+msgstr "Clients"
+
+msgid "Collaboration"
+msgstr "Collaboracion"
+
+msgid "Components"
+msgstr "Compausants"
+
+msgid "Rooms"
+msgstr "Charradors"
+
+msgid "Directories"
+msgstr "Repertòris"
+
+msgid "Gateways"
+msgstr "Passarèlas"
+
+msgid "News"
+msgstr "Actualitats"
+
+msgid "Hierarchy"
+msgstr "Ierarchia"
+
+msgid "Proxies"
+msgstr "Proxies"
+
+msgid "Publication/Subscription"
+msgstr ""
+
+msgid "Storage"
+msgstr "Emmagazinatge"
+
+msgid "Service offline or broken"
+msgstr ""
+
+msgid "Your inbox"
+msgstr "Vòstra boitia d'arribada"
+
+msgid "Available actions"
+msgstr ""
+
+msgid "Clean"
+msgstr "Voidar"
+
+msgid "New"
+msgstr "Noveu"
+
+msgid "Received"
+msgstr "Reçaugut"
+
+msgid "Subject"
+msgstr "Subjècte"
+
+msgid "Content"
+msgstr "Contengut"
+
+msgid "Send message"
+msgstr "Enviar lo messatge"
+
+msgid "Your inbox is empty."
+msgstr "Vòstra boitia d'arribada es voida"
+
+msgid "MUC administration"
+msgstr ""
+
+msgid "You administrate this room"
+msgstr ""
+
+msgid "Enter new subject"
+msgstr ""
+
+msgid "Configuration"
+msgstr "Configuracion"
+
+msgid "Authorizations"
+msgstr "Autorizacions"
+
+msgid "Member list"
+msgstr ""
+
+msgid "Owner list"
+msgstr ""
+
+msgid "Administrator list"
+msgstr ""
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr ""
+
+msgid "Yes, let's do it!"
+msgstr ""
+
+msgid "Your friend is paying attention to the conversation."
+msgstr ""
+
+msgid "Your friend is writing a message..."
+msgstr "Vòstre amic es a escriure un messatge..."
+
+msgid "Your friend stopped writing a message."
+msgstr ""
+
+msgid "Your friend is doing something else."
+msgstr ""
+
+msgid "Your friend closed the chat."
+msgstr ""
+
+msgid "Requesting this service..."
+msgstr ""
+
+msgid "Loading"
+msgstr "Charja"
+
+msgid "joined the chat room"
+msgstr ""
+
+msgid "left the chat room"
+msgstr ""
+
+msgid "no status"
+msgstr ""
+
+msgid "has been kicked"
+msgstr ""
+
+msgid "has been banned"
+msgstr ""
+
+msgid "no reason"
+msgstr ""
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr "Adiu !"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Benvengut/uda sus %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr "Precedent"
+
+msgid "General"
+msgstr "Generau"
+
+msgid "Advanced"
+msgstr "Avançat"
+
+msgid "Resource"
+msgstr ""
+
+msgid "Priority"
+msgstr "Prioritat"
+
+msgid "Low"
+msgstr "Bassa"
+
+msgid "Medium"
+msgstr "Mejana"
+
+msgid "High"
+msgstr "Nauta"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Picatz lo nom dau charrador que voletz junher e vòstre chafre. Podetz tanben tornar a la %s. "
+
+msgid "login page"
+msgstr ""
+
+msgid "Share this link with your friends:"
+msgstr ""
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr ""
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr ""
+
+msgid "Manager"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Encrypted"
+msgstr ""
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr "Ente setz ?"
+
+msgid "What's up with you?"
+msgstr ""
+
+msgid "Fetching the social channel..."
+msgstr ""
+
+msgid "You are synchronized with your network."
+msgstr ""
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr ""
+
+msgid "Media viewer"
+msgstr ""
+
+msgid "Browse"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Join"
+msgstr ""
+
+msgid "Automatic"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "No result!"
+msgstr ""
+
+msgid "No notifications."
+msgstr ""
+
+msgid "would like to add you as a friend."
+msgstr ""
+
+msgid "would like you to join this chatroom:"
+msgstr ""
+
+msgid "Do you accept?"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "would like to get authorization."
+msgstr ""
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Client"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "Local time"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "User profile"
+msgstr ""
+
+msgid "See his/her position on the globe"
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "anonymous mode"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Unclassified"
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Ask for authorization"
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Prohibit"
+msgstr ""
+
+msgid "Block"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Groupchat"
+msgstr ""
+
+msgid "Jappix Mobile"
+msgstr ""
+
+msgid "Desktop"
+msgstr ""
+
+msgid "Mobile"
+msgstr ""
+
+msgid "Please wait..."
+msgstr ""
+
+msgid "Please enable JavaScript"
+msgstr ""
+
+msgid "Your channel"
+msgstr ""
+
+msgid "Channel of"
+msgstr ""
+
+msgid "More notices..."
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Send"
+msgstr ""
+
+msgid "Unattach the file"
+msgstr ""
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr ""
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr ""
+
+msgid "Internal server error, try later"
+msgstr ""
+
+msgid "Your form has been sent."
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "XMPP links"
+msgstr ""
+
+msgid "Open XMPP links with Jappix"
+msgstr ""
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr ""
+
+msgid "Friends"
+msgstr "Amics"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr "Amics fòra linha"
+
+msgid "Don't hide offline friends"
+msgstr ""
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr ""
+
+msgid "Unknown country"
+msgstr ""
+
+msgid "Click to enable"
+msgstr ""
+
+msgid "Click to disable"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Jappix installation"
+msgstr ""
+
+msgid "Welcome to the Jappix installation!"
+msgstr ""
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr ""
+
+msgid "Storage configuration"
+msgstr ""
+
+msgid "Administrator account"
+msgstr ""
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr ""
+
+msgid "Services installation"
+msgstr ""
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr ""
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr "Utilizaire"
+
+msgid "Service"
+msgstr ""
+
+msgid "Service name"
+msgstr ""
+
+msgid "Service description"
+msgstr ""
+
+msgid "Connection"
+msgstr ""
+
+msgid "Lock the host"
+msgstr ""
+
+msgid "Anonymous mode"
+msgstr ""
+
+msgid "Registration allowed"
+msgstr ""
+
+msgid "Use a proxy"
+msgstr ""
+
+msgid "Encryption"
+msgstr ""
+
+msgid "HTTPS storage"
+msgstr ""
+
+msgid "Force HTTPS"
+msgstr ""
+
+msgid "Compression"
+msgstr ""
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr ""
+
+msgid "Groupchat host"
+msgstr ""
+
+msgid "Anonymous host"
+msgstr ""
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Finish"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr ""
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Hosts"
+msgstr ""
+
+msgid "Design"
+msgstr ""
+
+msgid "Repeat"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Horizontal"
+msgstr ""
+
+msgid "Vertical"
+msgstr ""
+
+msgid "Center"
+msgstr ""
+
+msgid "Left"
+msgstr ""
+
+msgid "Right"
+msgstr ""
+
+msgid "Top"
+msgstr ""
+
+msgid "Bottom"
+msgstr ""
+
+msgid "Adapt"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "You have been logged out. Goodbye!"
+msgstr ""
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr ""
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr "Genier"
+
+msgid "February"
+msgstr "Feurier"
+
+msgid "March"
+msgstr "Març"
+
+msgid "April"
+msgstr "Abriu"
+
+msgid "May"
+msgstr "Mai"
+
+msgid "June"
+msgstr "Junh"
+
+msgid "July"
+msgstr "Julhet"
+
+msgid "August"
+msgstr "Aust"
+
+msgid "September"
+msgstr "Septembre"
+
+msgid "October"
+msgstr "Octòbre"
+
+msgid "November"
+msgstr "Novembre"
+
+msgid "December"
+msgstr "Decembre"
+
+msgid "Monday"
+msgstr "Diluns"
+
+msgid "Tuesday"
+msgstr "Dimars"
+
+msgid "Wednesday"
+msgstr "Dimecres"
+
+msgid "Thursday"
+msgstr "Dijòus"
+
+msgid "Friday"
+msgstr "Divendres"
+
+msgid "Saturday"
+msgstr "Dissabde"
+
+msgid "Sunday"
+msgstr "Diumenc"
+
+msgid "Total"
+msgstr ""
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr "Musica"
+
+msgid "Backgrounds"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr ""
+
+msgid "Notice"
+msgstr ""
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr ""
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr ""
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr ""
+
+msgid "Update in progress"
+msgstr ""
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr ""
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr ""
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr ""
+
+msgid "Daily"
+msgstr ""
+
+msgid "Weekly"
+msgstr ""
+
+msgid "Monthly"
+msgstr ""
+
+msgid "Yearly"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Clean everything"
+msgstr ""
+
+msgid "Purge cache"
+msgstr ""
+
+msgid "Purge logs"
+msgstr ""
+
+msgid "Purge updates"
+msgstr ""
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Artist"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "The folder is empty."
+msgstr ""
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr ""
+
+msgid "The chosen users have been removed."
+msgstr ""
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "%s days ago"
+msgstr ""
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr ""
+
+msgid "Uncheck all"
+msgstr ""
+
+msgid "Choose"
+msgstr ""
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/pl/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/pl/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..8eed385
Binary files /dev/null and b/jappixmini/jappix/lang/pl/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/pl/LC_MESSAGES/main.po b/jappixmini/jappix/lang/pl/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..58bdb62
--- /dev/null
@@ -0,0 +1,1870 @@
+# Polish translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Obsługa JavaScript jest wyłączona przez co uruchomienie Jappix-a jest niemożliwe! Prosimy o aktywowanie obsługi JavaScript i spróbowanie ponownie."
+
+msgid "An open social network"
+msgstr "Otwarta sieć społecznościowa"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Działanie Jappix zostało przerwane przez problem sieciowy, błąd programu bądź złe dane logowania (sprawdź, czy podałeś prawidłowe dane dostępowe). Za usterkę przepraszamy."
+
+msgid "The element list on this server could not be obtained!"
+msgstr ""
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Hasło zostało zmienione. Możesz połączyć się do swojego konta używając nowego hasła."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Twoje konto XMPP zostało usunięte, żegnaj!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Wylogowywanie zakończone pomyślnie, życzymy miłego dnia!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Pokój do którego dołączyłeś nie istnieje. Powinieneś go stworzyć!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Pokój rozmów został usunięty, teraz ktoś inny będzie mógł go stworzyć."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Użytkownik z którym chciałeś się skontaktować nie jest obecny w pokoju."
+
+msgid "Please enter the group chat address to join."
+msgstr "Wprowadź adres pokoju czatowego aby do niego dołączyć."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Wprowadź swój nick aby dołączyć do %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Ten pokój (%s) jest chroniony hasłem."
+
+msgid "Your browser is out of date!"
+msgstr "Twoja przeglądarka jest nieaktualna!"
+
+msgid "Last %s version is better!"
+msgstr "Ostatnia wersja %s jest lepsza!"
+
+msgid "Login"
+msgstr "Login"
+
+msgid "Register"
+msgstr "Rejestracja"
+
+msgid "Here we go!"
+msgstr "Do dzieła!"
+
+msgid "Server"
+msgstr "Serwer"
+
+msgid "Password"
+msgstr "Hasło"
+
+msgid "Remember me"
+msgstr "Zapamiętaj mnie"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "To narzędzie zostało wyłączone, nie możesz z niego skorzystać!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Z powodu błędu sieci połączenie zostało zerwane. Co chcesz teraz zrobić?"
+
+msgid "Reconnect"
+msgstr "Połącz ponownie"
+
+msgid "Messages"
+msgstr "Wiadomości"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Opcje"
+
+msgid "Disconnect"
+msgstr "Wyloguj"
+
+msgid "Filter"
+msgstr "Filtr"
+
+msgid "Add a friend"
+msgstr "Dodaj znajomego"
+
+msgid "Your groupchats"
+msgstr "Twoje rozmowy grupowe"
+
+msgid "Manage your favorite groupchats"
+msgstr "Zarządzaj ulubionymi pokojami rozmów"
+
+msgid "More stuff"
+msgstr "Więcej"
+
+msgid "Show all friends"
+msgstr "Pokaż wszystkich znajomych"
+
+msgid "Only show connected friends"
+msgstr "Pokazuj tylko połączonych znajomych"
+
+msgid "Message archives"
+msgstr "Archiwum wiadomości"
+
+msgid "Date"
+msgstr "Data"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Wybierz znajomego aby zobaczyć archiwum."
+
+msgid "Nothing found for: %s"
+msgstr "Nic nieznaleziono dla: %s"
+
+msgid "A short message?"
+msgstr "Krótka wiadomość?"
+
+msgid "How are you?"
+msgstr "Jak się masz?"
+
+msgid "What are you doing?"
+msgstr "Co robisz?"
+
+msgid "Join a chat"
+msgstr "Dołącz do rozmowy"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "Available"
+msgstr "Dostępny"
+
+msgid "Talkative"
+msgstr "Chętny do rozmowy"
+
+msgid "Away"
+msgstr "Nieobecny"
+
+msgid "Not available"
+msgstr "Niedostępny"
+
+msgid "Busy"
+msgstr "Zajęty"
+
+msgid "Mood"
+msgstr "Nastrój"
+
+msgid "None"
+msgstr "Żaden"
+
+msgid "Crazy"
+msgstr "Zwariowany"
+
+msgid "Excited"
+msgstr "Podekscytowany"
+
+msgid "Playful"
+msgstr "Rozbawiony"
+
+msgid "Happy"
+msgstr "Wesoły"
+
+msgid "Shocked"
+msgstr "Zszokowany"
+
+msgid "Hot"
+msgstr "Gorący"
+
+msgid "Sad"
+msgstr "Smutny"
+
+msgid "Amorous"
+msgstr "Rozkochany"
+
+msgid "Confident"
+msgstr "Pewny siebie"
+
+msgid "Activity"
+msgstr "Aktywność"
+
+msgid "Chores"
+msgstr "Prace domowe"
+
+msgid "Drinking"
+msgstr "Picie"
+
+msgid "Eating"
+msgstr "Jedzenie"
+
+msgid "Exercising"
+msgstr "Ćwiczenia"
+
+msgid "Grooming"
+msgstr "Higiena"
+
+msgid "Appointment"
+msgstr "Spotkanie"
+
+msgid "Inactive"
+msgstr "Nieaktywne"
+
+msgid "Relaxing"
+msgstr "Relaksowanie"
+
+msgid "Talking"
+msgstr "Rozmowa"
+
+msgid "Traveling"
+msgstr "Podróżowanie"
+
+msgid "Working"
+msgstr "Praca"
+
+msgid "View profile"
+msgstr "Zobacz profil"
+
+msgid "Repeat this notice"
+msgstr "Powtórz tą informację"
+
+msgid "Remove this notice"
+msgstr "Usuń tą informację"
+
+msgid "Your profile"
+msgstr "Twój profil"
+
+msgid "Identity"
+msgstr "Tożsamość"
+
+msgid "Profile image"
+msgstr "Awatar"
+
+msgid "Others"
+msgstr "Inne"
+
+msgid "Personal"
+msgstr "Personalne"
+
+msgid "Complete name"
+msgstr "Imię i nazwisko"
+
+msgid "Nickname"
+msgstr "Pseudonim"
+
+msgid "First name"
+msgstr "Imię"
+
+msgid "Last name"
+msgstr "Nazwisko"
+
+msgid "Date of birth"
+msgstr "Data urodzenia"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefon"
+
+msgid "Website"
+msgstr "Strona internetowa"
+
+msgid "Current"
+msgstr "Aktualny"
+
+msgid "Delete"
+msgstr "Usuń"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Jaka szkoda! Nie masz ustawionego awatara!"
+
+msgid "Address"
+msgstr "Adres"
+
+msgid "Street"
+msgstr "Ulica"
+
+msgid "City"
+msgstr "Miejscowość"
+
+msgid "Postal code"
+msgstr "Kod pocztowy"
+
+msgid "Country"
+msgstr "Kraj"
+
+msgid "Biography"
+msgstr "Biografia"
+
+msgid "Important notice"
+msgstr "Ważna uwaga"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Uważaj jakie informację wpisujesz w swoim profilu ponieważ każdy może je zobaczyć (nawet ktoś niepożądany)"
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "W XMPP nie wszystko jest prywatne; to jedna z takich rzeczy, Twój publiczny profil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Zaleca się, aby przesłać obrazek profilowy (maksymalnie %s), w formie zdjęcia siebie samego, bo sprawi, że będziesz łatwo rozpoznawalny przez znajomych."
+
+msgid "Save"
+msgstr "Zapisz"
+
+msgid "Cancel"
+msgstr "Anuluj"
+
+msgid "Edit options"
+msgstr "Edytuj opcje"
+
+msgid "Channel"
+msgstr "Kanał"
+
+msgid "Commands"
+msgstr "Komendy"
+
+msgid "Sounds"
+msgstr "Dźwięki"
+
+msgid "Privacy"
+msgstr "Prywatność"
+
+msgid "Message archiving"
+msgstr "Archiwizacja wiadomości"
+
+msgid "Store a history of your chats"
+msgstr "Przechowuj historię rozmów"
+
+msgid "Geolocation"
+msgstr "Geolokalizacja"
+
+msgid "Empty"
+msgstr "Pusty"
+
+msgid "Empty channel"
+msgstr "Pusty kanał"
+
+msgid "Persistent"
+msgstr "Trwałe"
+
+msgid "Maximum notices"
+msgstr "Maksymalnie powiadomień"
+
+msgid "Account"
+msgstr "Konto"
+
+msgid "Change password"
+msgstr "Zmień hasło"
+
+msgid "Delete account"
+msgstr "Usuń konto"
+
+msgid "Old"
+msgstr "Stary"
+
+msgid "New (2 times)"
+msgstr "Nowe (dwa razy)"
+
+msgid "Continue"
+msgstr "Kontynuuj"
+
+msgid "To"
+msgstr "Do"
+
+msgid "Close"
+msgstr "Zamknij"
+
+msgid "unknown"
+msgstr "nieznany"
+
+msgid "Unavailable"
+msgstr "Niedostępny"
+
+msgid "is now"
+msgstr "jest teraz"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Proszę czekać, Twój awatar jest ładowany..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Oto i on! Piękny awatar!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Format obrazka jest niepoprawny lub obrazek ma zły rozmiar."
+
+msgid "Reply"
+msgstr "Odpowiedz"
+
+msgid "Error"
+msgstr "Błąd"
+
+msgid "Click here to solve the error"
+msgstr "Kliknij tutaj aby rozwiązać problem"
+
+msgid "You"
+msgstr "Ty"
+
+msgid "Remove"
+msgstr "Usuń"
+
+msgid "Rename"
+msgstr "Zmień nazwę"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Cześć, jestem %s, chciałbym abyś dodał mnie do swoich znajomych."
+
+msgid "Smiley insertion"
+msgstr "Wstaw emotikonę"
+
+msgid "Change style"
+msgstr "Zmień styl"
+
+msgid "Text in bold"
+msgstr "Pogrubiony tekst"
+
+msgid "Text in italic"
+msgstr "Pochyły tekst"
+
+msgid "Underlined text"
+msgstr "Podkreślony tekst"
+
+msgid "Save chat"
+msgstr "Zapisz rozmowę"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Kliknij poniższy link aby utworzyć zapis rozmowy i poczekaj. Później kliknij ponownie aby pobrać plik."
+
+msgid "This chat is empty!"
+msgstr "Ten czat jest pusty!"
+
+msgid "Generate file!"
+msgstr "Wygeneruj plik!"
+
+msgid "Download file!"
+msgstr "Pobierz plik!"
+
+msgid "Clean current chat"
+msgstr "Wyczyść okno rozmowy"
+
+msgid "View chat history"
+msgstr "Zobacz historię rozmów"
+
+msgid "Show user profile"
+msgstr "Pokaż profil użytkownika"
+
+msgid "Add this contact to your friends"
+msgstr "Dodaj kontakt do znajomych"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Dodaj ten pokój do ulubionych"
+
+msgid "All tabs"
+msgstr "Wszystkie zakładki"
+
+msgid "Close this tab"
+msgstr "Zamknij tą zakładkę"
+
+msgid "no subject defined for this room."
+msgstr "nie określono tematu dla tego pokoju."
+
+msgid "Administration panel for this room"
+msgstr "Panel administratora tego pokoju"
+
+msgid "Moderators"
+msgstr "Moderatorzy"
+
+msgid "Participants"
+msgstr "Uczestnicy"
+
+msgid "Visitors"
+msgstr "Odwiedzający"
+
+msgid "Manage favorite rooms"
+msgstr "Zarządzaj ulubionymi pokojami"
+
+msgid "Change favorites"
+msgstr "Zmień ulubione"
+
+msgid "Search a room"
+msgstr "Wyszukaj pokój"
+
+msgid "Select a favorite"
+msgstr "Wybierz ulubiony"
+
+msgid "Getting the name..."
+msgstr "Pobieranie nazwy..."
+
+msgid "Gateway"
+msgstr "Brama"
+
+msgid "Name"
+msgstr "Nazwa"
+
+msgid "Room"
+msgstr "Pokój"
+
+msgid "Add"
+msgstr "Dodaj"
+
+msgid "Edit"
+msgstr "Edytuj"
+
+msgid "Search a room on"
+msgstr "Szukaj pokoju na"
+
+msgid "No room found on this server."
+msgstr "Nie znaleziono pokoju na tym serwerze."
+
+msgid "Service discovery"
+msgstr "Przeglądarka usług"
+
+msgid "Server to query"
+msgstr "Serwer do odpytania"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr "Konta"
+
+msgid "Authentications"
+msgstr "Autentykacja"
+
+msgid "Automation"
+msgstr "Automatyzacja"
+
+msgid "Clients"
+msgstr "Klienci"
+
+msgid "Collaboration"
+msgstr "Współpraca"
+
+msgid "Components"
+msgstr "Komponenty"
+
+msgid "Rooms"
+msgstr "Pokoje"
+
+msgid "Directories"
+msgstr "Katalogi"
+
+msgid "Gateways"
+msgstr "Bramki"
+
+msgid "News"
+msgstr "Wiadomości"
+
+msgid "Hierarchy"
+msgstr "Hierarchia"
+
+msgid "Proxies"
+msgstr "Pośrednicy"
+
+msgid "Publication/Subscription"
+msgstr "Publikacje/subskrypcje"
+
+msgid "Storage"
+msgstr "Magazynowanie"
+
+msgid "Service offline or broken"
+msgstr "Usługa niedostępna bądź uszkodzona"
+
+msgid "Your inbox"
+msgstr "Twoja skrzynka odbiorcza"
+
+msgid "Available actions"
+msgstr "Dostępne działania"
+
+msgid "Clean"
+msgstr "Wyczyść"
+
+msgid "New"
+msgstr "Nowy"
+
+msgid "Received"
+msgstr "Odebrane"
+
+msgid "Subject"
+msgstr "Temat"
+
+msgid "Content"
+msgstr "Treść"
+
+msgid "Send message"
+msgstr "Wyślij wiadomość"
+
+msgid "Your inbox is empty."
+msgstr "Twoja skrzynka odbiorcza jest pusta."
+
+msgid "MUC administration"
+msgstr "Administracja MUC"
+
+msgid "You administrate this room"
+msgstr "Administrujesz tym pokojem"
+
+msgid "Enter new subject"
+msgstr "Podaj nowy temat"
+
+msgid "Configuration"
+msgstr "Konfiguracja"
+
+msgid "Authorizations"
+msgstr "Autoryzacja"
+
+msgid "Member list"
+msgstr "Lista członków"
+
+msgid "Owner list"
+msgstr "Lista właścicieli"
+
+msgid "Administrator list"
+msgstr "Lista administratorów"
+
+msgid "Outcast list"
+msgstr "Lista wykluczonych"
+
+msgid "Add an input"
+msgstr "Dodaj wpis"
+
+msgid "Destroy this MUC"
+msgstr "Usuń ten MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Tak, zróbmy to!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Twój znajomy przygląda się rozmowie."
+
+msgid "Your friend is writing a message..."
+msgstr "Twój znajomy pisze wiadomość..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Twój znajomy przestał pisać."
+
+msgid "Your friend is doing something else."
+msgstr "Twój znajomy robi coś innego."
+
+msgid "Your friend closed the chat."
+msgstr "Twój znajomy zamknął rozmowę."
+
+msgid "Requesting this service..."
+msgstr "Żądanie usługi..."
+
+msgid "Loading"
+msgstr "Ładowanie"
+
+msgid "joined the chat room"
+msgstr "dołączył(a) do czatu"
+
+msgid "left the chat room"
+msgstr "opuścił(a) czat"
+
+msgid "no status"
+msgstr "brak statusu"
+
+msgid "has been kicked"
+msgstr "został(a) wyrzucony"
+
+msgid "has been banned"
+msgstr "został(a) zbanowany"
+
+msgid "no reason"
+msgstr "brak powodu"
+
+msgid "Communicate with the entire world!"
+msgstr "Rozmawiaj z całym światem!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Pozwala Ci być w kontakcie z milionami użytkowników, którzy używają obecnie sieci XMPP, tak jak Ty obecnie łączysz się doń przez Jappixa. Dołącz do społeczności i stań się wolny!"
+
+msgid "Hi there!"
+msgstr "Cześć wam!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Witamy na %1s, “%2s“."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Zaloguj się do swojego konta XMPP lub stwórz nowe - za darmo!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix to projekt open-source od PostPro - organizacja non-profit która służy wspaniałą pomocą."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Zaloguj się do twojego istniejącego konta XMPP. Możesz również użyć %s aby dołączyć do pokojów czatowych."
+
+msgid "Previous"
+msgstr "Poprzedni"
+
+msgid "General"
+msgstr "Ogólny"
+
+msgid "Advanced"
+msgstr "Zaawansowane"
+
+msgid "Resource"
+msgstr "Zasób"
+
+msgid "Priority"
+msgstr "Priorytet"
+
+msgid "Low"
+msgstr "Niski"
+
+msgid "Medium"
+msgstr "Średni"
+
+msgid "High"
+msgstr "Wysoki"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Dołącz do dowolnego czatu z nickiem, który chcesz mieć. Możesz też wrócić do %s."
+
+msgid "login page"
+msgstr "strona logowania"
+
+msgid "Share this link with your friends:"
+msgstr "Podziel się linkiem z przyjaciółmi:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Załóż nowe konto XMPP by dołączyć do twoich przyjaciół w twojej własnej społeczności. To proste!"
+
+msgid "Required"
+msgstr "Wymagane"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Rejestracja przebiegła pomyślnie! Oto Twój adres XMPP:"
+
+msgid "Manager"
+msgstr "Menedżer"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Szyfrowane"
+
+msgid "Unencrypted"
+msgstr "Nieszyfrowane"
+
+msgid "Where are you?"
+msgstr "Gdzie jesteś?"
+
+msgid "What's up with you?"
+msgstr "Co u Ciebie słychać?"
+
+msgid "Fetching the social channel..."
+msgstr "Pobieranie kanału publicznego..."
+
+msgid "You are synchronized with your network."
+msgstr "Jesteś połączony ze swoją siecią."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Nie można nic wysłać: możesz jedynie otrzymywać powiadomienia!"
+
+msgid "Media viewer"
+msgstr "Odtwarzacz multimediów"
+
+msgid "Browse"
+msgstr "Przeglądaj"
+
+msgid "Command"
+msgstr "Komenda"
+
+msgid "Subscribe"
+msgstr "Subskrybuj"
+
+msgid "Join"
+msgstr "Dołącz"
+
+msgid "Automatic"
+msgstr "Automatycznie"
+
+msgid "Search"
+msgstr "Szukaj"
+
+msgid "No result!"
+msgstr "Brak wyników!"
+
+msgid "No notifications."
+msgstr "Brak powiadomień."
+
+msgid "would like to add you as a friend."
+msgstr "chciałby dodać Cię jako znajomego."
+
+msgid "would like you to join this chatroom:"
+msgstr "chciałby prosić Cię o dołączenie do tego pokoju: "
+
+msgid "Do you accept?"
+msgstr "Czy się zgadzasz?"
+
+msgid "Yes"
+msgstr "Tak"
+
+msgid "No"
+msgstr "Nie"
+
+msgid "would like to get authorization."
+msgstr "prosi o autoryzację."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr "Wyślij"
+
+msgid "Client"
+msgstr "Klient"
+
+msgid "System"
+msgstr "System"
+
+msgid "Local time"
+msgstr "Czas lokalny"
+
+msgid "Comments"
+msgstr "Komentarze"
+
+msgid "User profile"
+msgstr "Profil użytkownika"
+
+msgid "See his/her position on the globe"
+msgstr "Zobacz jej/jego położenie geograficzne"
+
+msgid "Confirm"
+msgstr "Potwierdź"
+
+msgid "anonymous mode"
+msgstr "tryb anonimowy"
+
+msgid "Groups"
+msgstr "Grupy"
+
+msgid "Unclassified"
+msgstr "Nieklasyfikowane"
+
+msgid "Authorize"
+msgstr "Autoryzuj"
+
+msgid "Ask for authorization"
+msgstr "Zapytaj o autoryzację"
+
+msgid "Unblock"
+msgstr "Odblokuj"
+
+msgid "Prohibit"
+msgstr "Zabroń"
+
+msgid "Block"
+msgstr "Blokuj"
+
+msgid "Chat"
+msgstr "Rozmowa"
+
+msgid "Groupchat"
+msgstr "Rozmowa grupowa"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobile"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Mobilny"
+
+msgid "Please wait..."
+msgstr "Proszę czekać..."
+
+msgid "Please enable JavaScript"
+msgstr "Proszę włączyć JavaScript"
+
+msgid "Your channel"
+msgstr "Twój kanał"
+
+msgid "Channel of"
+msgstr "Kanał"
+
+msgid "More notices..."
+msgstr "Więcej powiadomień..."
+
+msgid "Attach a file"
+msgstr "Załącz plik"
+
+msgid "Send"
+msgstr "Wyślij"
+
+msgid "Unattach the file"
+msgstr "Odłącz plik"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Wystąpił błąd podczas wysyłania pliku: możliwe że jest zbyt duży (maksymalnie %s) bądź zablokowany!"
+
+msgid "Authorization failed"
+msgstr "Autoryzacja nie powiodła się"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Rejestracja nie powiodła się, proszę wybrać inną nazwę użytkownika"
+
+msgid "Service unavailable"
+msgstr "Usługa niedostępna"
+
+msgid "Internal server error, try later"
+msgstr "Wewnętrzny błąd serwera, proszę spróbować później."
+
+msgid "Your form has been sent."
+msgstr "Twój formularz został wysłany."
+
+msgid "Application"
+msgstr "Aplikacja"
+
+msgid "XMPP links"
+msgstr "linki XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Otwieraj linki XMPP w Jappix"
+
+msgid "changed the subject to:"
+msgstr "zmień temat na:"
+
+msgid "Welcome!"
+msgstr "Witamy!"
+
+msgid "Friends"
+msgstr "Znajomi"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Witaj w Jappix-ie, Twojej własnej socjalnej chmurze!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Zanim zaczniesz tego używać, musisz zmienić niektóre ustawienia, znaleźć znajomych i uzupełnić swój profil."
+
+msgid "Enable notification sounds"
+msgstr "Włącz powiadomienia dźwiękowe"
+
+msgid "Share your position on the globe"
+msgstr "Dziel się swoją aktualną pozycją"
+
+msgid "Offline friends"
+msgstr "Rozłączeni znajomi"
+
+msgid "Don't hide offline friends"
+msgstr "Nie ukrywaj rozłączonych znajomych"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Użyj tego narzędzia do znalezienia Twoich znajomych na serwerze, którego używasz, lub dodaj ich później."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr "Nazwa nieznana"
+
+msgid "Unknown country"
+msgstr "Kraj nieznany"
+
+msgid "Click to enable"
+msgstr "Kliknij by włączyć"
+
+msgid "Click to disable"
+msgstr "Kliknij by wyłączyć"
+
+msgid "Installation"
+msgstr "Instalacja"
+
+msgid "Jappix installation"
+msgstr "Instalacja Jappixa"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Witaj w instalacji Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "To narzędzie pomoże Ci szybko zainstalować Jappix-a, pierwszą platformę społecznościową opartą o protokół XMPP."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Zobaczmy kroki instalacji:"
+
+msgid "Welcome"
+msgstr "Witamy"
+
+msgid "Storage configuration"
+msgstr "Konfiguracja folderów"
+
+msgid "Administrator account"
+msgstr "Konto administratora"
+
+msgid "Main configuration"
+msgstr "Konfiguracja główna"
+
+msgid "Hosts configuration"
+msgstr "Konfiguracja hostów"
+
+msgid "Services installation"
+msgstr "Instalacja usług"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Jeśli aktualny język Ci nie pasuję (%1s), możesz zmienić go na %2s."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Jeśli potrzebujesz więcej informacji dotyczących instalacji i konfiguracji Jappixa, możesz użyć dokumentacji dostępnej pod adresem:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Już pora zbudować twoją własną socjalną chmórę: przejdź do następnego kroku!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix przechowuje stałe dane (takie jak publikowane pliki, archiwa rozmów, pliki dźwiękowe wraz z konfiguracją) w jednym zabezpieczonym folderze."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix musi mieć możliwość zapisu w tym folderze aby móc stworzyć w nim pod-foldery. Jeśli nie, musisz ustawić prawa na %1s lub zmienić właściciela folderu na %2s (w zależności od konfiguracji)"
+
+msgid "The folder is writable, you can continue!"
+msgstr "Można zapisywać w folderze, możesz kontynuować!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix oferuje Ci możliwość zarządzania konfiguracją, instalacji nowych pluginów lub sprawdzania aktualizacji. To właśnie dlatego musisz stworzyć konto administratora."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Kiedy Jappix będzie już zainstalowany, kliknij w link Menedżer na stronie głównej."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Ups! coś pominięto lub hasła nie pasują do siebie!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix wymaga wprowadzenia niektórych danych. Proszę poprawić następujące dane (lub pozostaw domyślne wartości, które są wystarczające dla większości ludzi)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Jeśli nie wypełnisz wymaganego pola, zostanie ono automatycznie wypełnione domyślną wartością."
+
+msgid "User"
+msgstr "Użytkownik"
+
+msgid "Service"
+msgstr "Usługa"
+
+msgid "Service name"
+msgstr "Nazwa usługi"
+
+msgid "Service description"
+msgstr "Opis usługi"
+
+msgid "Connection"
+msgstr "Połączenie"
+
+msgid "Lock the host"
+msgstr "Zablokuj hosta"
+
+msgid "Anonymous mode"
+msgstr "Tryb anonimowy"
+
+msgid "Registration allowed"
+msgstr "Rejestracja włączona"
+
+msgid "Use a proxy"
+msgstr "Użyj serwera proxy"
+
+msgid "Encryption"
+msgstr "Szyfrowanie"
+
+msgid "HTTPS storage"
+msgstr "Magazyn HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Wymuś HTTPS"
+
+msgid "Compression"
+msgstr "Kompresja"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Ta strona pomoże Ci ustawić domyślne hosty, do których Jappix będzie się łączyć. Możesz zostawić to tak jak jest i kontynuować jeśli chcesz korzystać z oficjalnych hostów."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Być może nie wiesz czym jest serwer BOSH? Jest to swoisty most łączący klienta Jappix-a i serwer XMPP. Jest on niezbędny ze względów technicznych."
+
+msgid "Main host"
+msgstr "Host główny"
+
+msgid "Groupchat host"
+msgstr "Host rozmów grupowych"
+
+msgid "Anonymous host"
+msgstr "Host anonimowy"
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr "host BOSH"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Możesz zainstalować dodatkowe oprogramowanie na serwerze, które wzbogaci możliwości Jappix-a. Inne może być zmodyfikowane ze względu na domyślne ustawienia prywatności."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Aby to wykonać, musisz mieć dostęp do shella na swoim serwerze i być zalogowanym jako root. Pamiętaj, że jest to opcjonalne, Jappix będzie działać bez tych modułów ale niektóre z jego możliwości będą niedostępne."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Po skonfigurowaniu, Jappix wygeneruje pliki cache. Może to długo potrwać, poczekaj aż aplikacja będzie pokazana i nie wciskaj żadnego klawisza."
+
+msgid "Thanks for using Jappix!"
+msgstr "Dziękujemy za używanie Jappix!"
+
+msgid "Next"
+msgstr "Dalej"
+
+msgid "Finish"
+msgstr "Koniec"
+
+msgid "Check again"
+msgstr "Sprawdź ponownie"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Folder nie jest zapisywalny, ustaw odpowiednie uprawienia dla folderu %s."
+
+msgid "%s is installed on your system."
+msgstr "%s jest zainstalowane w Twoim systemie."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s nie jest zainstalowane w Twoim systemie."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "Maksymalny rozmiar wysyłanego pliku ustawiony dla PHP jest wystarczający (%s)"
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "Maksymalny rozmiar wysyłanego pliku ustawiony dla PHP jest niewystarczający (%1s), powinieneś ustawić go na %2s w %3s."
+
+msgid "Jappix manager"
+msgstr "Menedżer Jappix"
+
+msgid "Manager access"
+msgstr "Dostęp menadżera"
+
+msgid "Statistics"
+msgstr "Statystyki"
+
+msgid "Hosts"
+msgstr "Hosty"
+
+msgid "Design"
+msgstr "Wygląd"
+
+msgid "Repeat"
+msgstr "Powtarzanie"
+
+msgid "All"
+msgstr "Wszystko"
+
+msgid "Horizontal"
+msgstr "Poziomo"
+
+msgid "Vertical"
+msgstr "Pionowo"
+
+msgid "Center"
+msgstr "Środek"
+
+msgid "Left"
+msgstr "Lewa"
+
+msgid "Right"
+msgstr "Prawa"
+
+msgid "Top"
+msgstr "Góra"
+
+msgid "Bottom"
+msgstr "Dół"
+
+msgid "Adapt"
+msgstr "Przystosuj"
+
+msgid "Color"
+msgstr "Kolor"
+
+msgid "Users"
+msgstr "Użytkownicy"
+
+msgid "Updates"
+msgstr "Akrualizacje"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Strefa zamknięta: tylko autoryzowani użytkownicy mogą zarządzać ustawieniami instalacji Jappix-a."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Użyj poniższego formularza aby zalogować się do panelu administracyjnego."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "W celu zwiększenia bezpieczeństwa, sesje są ograniczone czasowo - kiedy wyłączysz przeglądarke, zostaniesz wylogowany."
+
+msgid "Credentials"
+msgstr "Uprawnienia"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Zostałeś wylogowany. Żegnaj!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Ups. Nie zostałeś rozpoznany jako administrator, Sprawdź swoje uprawnienia!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Poniżej znajdziesz podstawowe statystyki instalacji Jappix-a."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Za pomocą tego narzędzia możesz zmienić ustawienia instalacji Jappix-a."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Zmień hosty XMPP, z którymi ma współpracować ta instalacja Jappix-a."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Za pomocą tego narzędzia możesz zarządzać wszystkimi zgromadzonymi przez Jappix-a plikami: proszę wybrać pod-folder i rozpocząć edycję zawartości!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix jest w pełni dostosowywalny: tu możesz zmienić jego wygląd."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "To nie jest poprawny obrazek, proszę użyć PNG, GIF lub JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Obrazek nie został pobrany, czy mógł byś spróbować ponownie?"
+
+msgid "Your image was added to the list!"
+msgstr "Twój obrazek został dodany do listy!"
+
+msgid "Changes saved!"
+msgstr "Zmiany zapisane!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Możesz ustawić więcej niż jednego administratora dla tej instalacji Jappix-a. Z pomocą tego narzędzia możesz też zmienić hasło."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Za pomocą tego narzędzia możesz zaktualizować swoją instalacje Jappix-a lub sprawdzić, czy dostępne są nowe wersje."
+
+msgid "Access statistics"
+msgstr "Statystyki odwiedzin"
+
+msgid "Share statistics"
+msgstr "Statystyki udostępniania"
+
+msgid "Other statistics"
+msgstr "Inne statystyki"
+
+msgid "January"
+msgstr "Styczeń"
+
+msgid "February"
+msgstr "Luty"
+
+msgid "March"
+msgstr "Marzec"
+
+msgid "April"
+msgstr "Kwiecień"
+
+msgid "May"
+msgstr "Maj"
+
+msgid "June"
+msgstr "Czerwiec"
+
+msgid "July"
+msgstr "Lipiec"
+
+msgid "August"
+msgstr "Sierpień"
+
+msgid "September"
+msgstr "Wrzesień"
+
+msgid "October"
+msgstr "Październik"
+
+msgid "November"
+msgstr "Listopad"
+
+msgid "December"
+msgstr "Grudzień"
+
+msgid "Monday"
+msgstr "Poniedziałek"
+
+msgid "Tuesday"
+msgstr "Wtorek"
+
+msgid "Wednesday"
+msgstr "Środa"
+
+msgid "Thursday"
+msgstr "Czwartek"
+
+msgid "Friday"
+msgstr "Piątek"
+
+msgid "Saturday"
+msgstr "Sobota"
+
+msgid "Sunday"
+msgstr "Niedziela"
+
+msgid "Total"
+msgstr "Łącznie"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Logi"
+
+msgid "Music"
+msgstr "Muzyka"
+
+msgid "Backgrounds"
+msgstr "Tła"
+
+msgid "Share"
+msgstr "Podziel się"
+
+msgid "Background"
+msgstr "Tło"
+
+msgid "Notice"
+msgstr "Informacja"
+
+msgid "Your design preferences have been saved!"
+msgstr "Ustawienia wyglądu zostały zapisane!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Proszę sprawdzić wprowadzone dane: coś jest nie tak!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Za pomocą tego narzędznia zmienisz tło w swojej instalacji Jappix-a. Możesz albo ustawić kolor albo wgrać obrazek. "
+
+msgid "Use default background"
+msgstr "Użyj domyślnego tła"
+
+msgid "Use your own image"
+msgstr "Użyj własnego obrazka"
+
+msgid "Select a background to use and change the display options."
+msgstr "Wybierz tło i zmień ustawienia wyświetlania."
+
+msgid "Use your own color"
+msgstr "Użyj własnego koloru."
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Podaj wartość hex koloru, który chcesz użyć jako tło."
+
+msgid "Manage backgrounds"
+msgstr "Zarządzaj obrazkami tła"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Za pomocą tego narzędzia możesz dodać nowe tło do listy. Proszę wysłać poprawny obrazek."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Jeśli chcesz usunąć niektóre tła, użyj poniższej przeglądarki."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Ustaw wiadomość powitalną dla wszystkich swoich użytkowników. Np. ostrzeżenie, ważna aktualizacja czy reklama."
+
+msgid "Simple notice"
+msgstr "Zwykłe powiadomienie"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "To powiadomienie potrzebuje tylko zwykłego tekstu, kod nie jest dozwolony!"
+
+msgid "Advanced notice"
+msgstr "Zaawansowane powiadomienie"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Możesz dostosować powiadomienie za pomocą HTML, CSS i JavaScript  ale musisz zakodować wygląd."
+
+msgid "Available updates"
+msgstr "Dostępne aktualizacje"
+
+msgid "What's new?"
+msgstr "Co nowego?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Nowa wersja Jappix-a jest dostępna! Sprawdź co nowego i uruchom aktualizator!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Twoja wersja jest nieaktualna. Zaktualizuj ją do %s kilkając tu!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Wygląda na to, że Twoja wersja jest aktualna ale możesz sprawdzić ją ręcznie klikając tutaj."
+
+msgid "Check for updates"
+msgstr "Sprawdź aktualizacje"
+
+msgid "Update in progress"
+msgstr "Aktualizacja w toku."
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix został zaktualizowany: teraz używasz najnowszej wersji. Miłej zabawy!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Aktualizacja nie powiodła się! Proszę spróbować później."
+
+msgid "Downloading package..."
+msgstr "Ściąganie paczki..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Usuwanie plików systemowych Jappix-a..."
+
+msgid "Extracting package..."
+msgstr "Rozpakowywanie paczki..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Wygeneruj ponownie drzewo folderu magazynującego..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix jest teraz zaktualizowany!"
+
+msgid "Aborted: socket error!"
+msgstr "Przerwano: błąd socket-a!"
+
+msgid "Aborted: buffer error!"
+msgstr "Przerwano: błąd bufora!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Przerwano: nie wszystko jest zapisywalne!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Przerwano: nie można rozpakować paczki!"
+
+msgid "Visits"
+msgstr "Wizyty"
+
+msgid "Daily"
+msgstr "Dziennie"
+
+msgid "Weekly"
+msgstr "Tygodniowo"
+
+msgid "Monthly"
+msgstr "Miesięcznie"
+
+msgid "Yearly"
+msgstr "Rocznie"
+
+msgid "Size"
+msgstr "Rozmiar"
+
+msgid "Clean everything"
+msgstr "Wyczyść wszystko"
+
+msgid "Purge cache"
+msgstr "Wyczyść cache"
+
+msgid "Purge logs"
+msgstr "Wyczyść logi"
+
+msgid "Purge updates"
+msgstr "Wyczyść aktualizacje"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Folder, który chciano wyczyścić jest teraz pusty!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Utrzymuj swoją instalację Jappix-a świeżego i szybkiego, czyść foldery foldery 'store' regularnie!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Wyślij swoją muzykę (Ogg Vorbis, MP3 lub WAV) i słuchaj jej w Jappix-ie!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Plik, który chcesz wysłać, musi być mniejszy niż %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Bądź na bieżąco z tym, co Twoi użytkownicy przechowują na serwerze i za pomocą tego urządzenia usuwaj niepożądane treści."
+
+msgid "Title"
+msgstr "Tytuł"
+
+msgid "Artist"
+msgstr "Wykonawca"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Plik"
+
+msgid "Upload"
+msgstr "Upload"
+
+msgid "The folder is empty."
+msgstr "Folder jest pusty,"
+
+msgid "The music could not be received, please retry!"
+msgstr "Muzyka nie została wczytana, proszę spróbować ponownie!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "To nie jest poprawny plik muzyczny, proszę wysłać plik Ogg Vorbis, MP3 lub WAV!"
+
+msgid "Your music has been added!"
+msgstr "Twoja muzyja została dodana!"
+
+msgid "The selected elements have been removed."
+msgstr "Zaznaczone elementy zostały usunięte."
+
+msgid "You must select elements to remove!"
+msgstr "Musisz zaznaczyć elementy do usunięcia!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Za pomocą tego narzędzia dodasz nowego użytkownika lub zmienisz hasło (wpisz istniejącą nazwę użytkownika). Pamiętaj, żeby wybrać mocne hasło!"
+
+msgid "Manage"
+msgstr "Zarządzaj"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Za pomocą tego narzędzia usuniesz użytkowników. Pamiętaj, że nie możesz usunąć użytkownika jeśli jest on jedynym pozostałym."
+
+msgid "The user has been added!"
+msgstr "Użytkownik został dodany!"
+
+msgid "The chosen users have been removed."
+msgstr "Wybrani użytkownicy zostali usunięci."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Musisz wybrać jednego lub kilku użytkowników do usunięcia!"
+
+msgid "Yesterday"
+msgstr "Wczoraj"
+
+msgid "%s days ago"
+msgstr "%s dni temu"
+
+msgid "User currently active"
+msgstr "User jest aktualnie aktywny"
+
+msgid "Last seen: %s"
+msgstr "Ostatnio widziany: %s"
+
+msgid "Inactive since: %s"
+msgstr "Nieaktywny od: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr "Zaznacz wszystkie"
+
+msgid "Uncheck all"
+msgstr "Odznacz wszystkie"
+
+msgid "Choose"
+msgstr "Wybierz"
+
+msgid "List name"
+msgstr "Nazwa listy"
+
+msgid "Allow"
+msgstr "Zezwól"
+
+msgid "Deny"
+msgstr "Zabroń"
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix jest społecznościową platrofmą non-profit, za pomocą której możesz komunikować się z kim chcesz, kiedy chcesz i skąd chcesz."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..3c4bad6
Binary files /dev/null and b/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.po b/jappixmini/jappix/lang/pt-BR/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..deef5ba
--- /dev/null
@@ -0,0 +1,1870 @@
+# Brazilian Portuguese translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:44+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript está faltando no seu navegador web, de modo que você não será capaz de lançar Jappix! Corrija isso."
+
+msgid "An open social network"
+msgstr "Uma rede social aberta"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix foi interrompido por um problema de rede, um login errado (verifique se você inseriu as credenciais correta), Desculpe pelo transtorno."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "A lista de elementos sobre esse servidor não pôde ser obtida!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Sua senha foi mudada, agora você pode se conectar a sua conta com os seus dados de login nova."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Sua conta XMPP foi removida, tchau!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Você foi deslogado da sua conta XMPP,  tenha um bom dia!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "A sala em que você entrou parece não existir. Você deve cria-la!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "O grupo de chat foi removido, agor alguém terá que recria-lo"
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "O usuário com quem quer se comunicar não está presente na sala."
+
+msgid "Please enter the group chat address to join."
+msgstr "Por favor insira o endereço do grupo de chat para entrar."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Por favor, digite um nome para se conectar em"
+
+msgid "This room (%s) is protected with a password."
+msgstr "Esta sala está protegida por uma senha."
+
+msgid "Your browser is out of date!"
+msgstr "Seu navegador esta desatualizado"
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr "Logar"
+
+msgid "Register"
+msgstr "Registrar"
+
+msgid "Here we go!"
+msgstr "E lá vamos nós!"
+
+msgid "Server"
+msgstr "Servidor"
+
+msgid "Password"
+msgstr "Senha"
+
+msgid "Remember me"
+msgstr "Me lembrar"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Esta ferramenta foi desativada. Você não pode usá-la!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Devido à problemas de rede, você foi desconectado. O que você quer fazer agora?"
+
+msgid "Reconnect"
+msgstr "Reconectar"
+
+msgid "Messages"
+msgstr "Mensagens"
+
+msgid "Profile"
+msgstr "Perfil"
+
+msgid "Options"
+msgstr "Opções"
+
+msgid "Disconnect"
+msgstr "Desconectar"
+
+msgid "Filter"
+msgstr "Filtrar"
+
+msgid "Add a friend"
+msgstr "Adicionar um amigo"
+
+msgid "Your groupchats"
+msgstr "Suas salas"
+
+msgid "Manage your favorite groupchats"
+msgstr "Administrar suas salas favoritas"
+
+msgid "More stuff"
+msgstr "Mais coisas"
+
+msgid "Show all friends"
+msgstr "Mostrar todos os amigos"
+
+msgid "Only show connected friends"
+msgstr "Mostrar apenas os amigos conectados"
+
+msgid "Message archives"
+msgstr "Arquivo de mensagens"
+
+msgid "Date"
+msgstr "Data"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Selecione o amigo que desejar ver o histórico"
+
+msgid "Nothing found for: %s"
+msgstr "Não encontrado para:"
+
+msgid "A short message?"
+msgstr "Uma mensagem curta?"
+
+msgid "How are you?"
+msgstr "Como vai você?"
+
+msgid "What are you doing?"
+msgstr "O que você tem feito?"
+
+msgid "Join a chat"
+msgstr "Entrar na sala"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "Available"
+msgstr "Disponível"
+
+msgid "Talkative"
+msgstr "Em conversa"
+
+msgid "Away"
+msgstr "Ausente"
+
+msgid "Not available"
+msgstr "Não disponível"
+
+msgid "Busy"
+msgstr "Ocupado"
+
+msgid "Mood"
+msgstr "Humor"
+
+msgid "None"
+msgstr "Nada"
+
+msgid "Crazy"
+msgstr "Louco"
+
+msgid "Excited"
+msgstr "Animado"
+
+msgid "Playful"
+msgstr "Brincalhão"
+
+msgid "Happy"
+msgstr "Feliz"
+
+msgid "Shocked"
+msgstr "Chocado"
+
+msgid "Hot"
+msgstr "Quente"
+
+msgid "Sad"
+msgstr "Triste"
+
+msgid "Amorous"
+msgstr "Amoroso"
+
+msgid "Confident"
+msgstr "Confiante"
+
+msgid "Activity"
+msgstr "Atividade"
+
+msgid "Chores"
+msgstr "Tarefas"
+
+msgid "Drinking"
+msgstr "Bebendo"
+
+msgid "Eating"
+msgstr "Comendo"
+
+msgid "Exercising"
+msgstr "Se exercitando"
+
+msgid "Grooming"
+msgstr "Aparência"
+
+msgid "Appointment"
+msgstr "nomeação"
+
+msgid "Inactive"
+msgstr "Inativo"
+
+msgid "Relaxing"
+msgstr "Relaxante"
+
+msgid "Talking"
+msgstr "Falando"
+
+msgid "Traveling"
+msgstr "Viajando"
+
+msgid "Working"
+msgstr "Trabalhando"
+
+msgid "View profile"
+msgstr "Ver Perfil"
+
+msgid "Repeat this notice"
+msgstr "Repetir a notícia"
+
+msgid "Remove this notice"
+msgstr "Remover esta notícia"
+
+msgid "Your profile"
+msgstr "Seu perfil"
+
+msgid "Identity"
+msgstr "Identidade"
+
+msgid "Profile image"
+msgstr "Imagem do perfil"
+
+msgid "Others"
+msgstr "Outros"
+
+msgid "Personal"
+msgstr "Pessoal"
+
+msgid "Complete name"
+msgstr "Nome completo"
+
+msgid "Nickname"
+msgstr "Apelido"
+
+msgid "First name"
+msgstr "Primeiro nome"
+
+msgid "Last name"
+msgstr "Sobrenome"
+
+msgid "Date of birth"
+msgstr "Data de aniversário"
+
+msgid "Contact"
+msgstr "Contato"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefone"
+
+msgid "Website"
+msgstr "Site"
+
+msgid "Current"
+msgstr "Atual"
+
+msgid "Delete"
+msgstr "Deletar"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Que pena! Você não possui imagem de perfil definida no seu cartão de identidade!"
+
+msgid "Address"
+msgstr "Endereço"
+
+msgid "Street"
+msgstr "Rua"
+
+msgid "City"
+msgstr "Cidade"
+
+msgid "Postal code"
+msgstr "Código Posta"
+
+msgid "Country"
+msgstr "País"
+
+msgid "Biography"
+msgstr "Biografia"
+
+msgid "Important notice"
+msgstr "Aviso importante"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr ""
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr ""
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "É recomendável o envio de uma imagem de perfil (%s máximo), como uma foto sua, isso facilita seu reconhecimento"
+
+msgid "Save"
+msgstr "Salvar"
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+msgid "Edit options"
+msgstr "Editar opções"
+
+msgid "Channel"
+msgstr "Canal"
+
+msgid "Commands"
+msgstr "Comandos"
+
+msgid "Sounds"
+msgstr "sons"
+
+msgid "Privacy"
+msgstr "Privacidade"
+
+msgid "Message archiving"
+msgstr "Arquivo de mensagens"
+
+msgid "Store a history of your chats"
+msgstr "Gravar o histórico das conversas"
+
+msgid "Geolocation"
+msgstr "Localização geográfica"
+
+msgid "Empty"
+msgstr "Vazio"
+
+msgid "Empty channel"
+msgstr "Canal vazio"
+
+msgid "Persistent"
+msgstr "Persistente"
+
+msgid "Maximum notices"
+msgstr "Máximo de avisos"
+
+msgid "Account"
+msgstr "Conta"
+
+msgid "Change password"
+msgstr "Mudar senha"
+
+msgid "Delete account"
+msgstr "Deletar conta"
+
+msgid "Old"
+msgstr "Velho"
+
+msgid "New (2 times)"
+msgstr "Novo (2 vezes)"
+
+msgid "Continue"
+msgstr "Continue"
+
+msgid "To"
+msgstr "Para"
+
+msgid "Close"
+msgstr "Fechar"
+
+msgid "unknown"
+msgstr "desconhecido"
+
+msgid "Unavailable"
+msgstr "Indisponível"
+
+msgid "is now"
+msgstr "É agora"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Por favor aguarde enquanto seu avatar é enviado..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Aqui está! Uma linda imagem nova de perfil!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "O arquivo da imagem não é suportado ou o tamanho é inválido."
+
+msgid "Reply"
+msgstr "Responder"
+
+msgid "Error"
+msgstr "Erro"
+
+msgid "Click here to solve the error"
+msgstr "Clique aqui para solucionar o erro"
+
+msgid "You"
+msgstr "Você"
+
+msgid "Remove"
+msgstr "Remover"
+
+msgid "Rename"
+msgstr "Renomear"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Olá, eu sou %s, eu gostaria de te adicionar como meu amigo."
+
+msgid "Smiley insertion"
+msgstr "Inserir emoticom"
+
+msgid "Change style"
+msgstr "Alterar estilo"
+
+msgid "Text in bold"
+msgstr "Texto em negrito"
+
+msgid "Text in italic"
+msgstr "Texto em itálico"
+
+msgid "Underlined text"
+msgstr "Texto sublinhado"
+
+msgid "Save chat"
+msgstr "Salvar conversa"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Clique no link a seguir para acessar o log da conversa. Após um tempo, clique novamente para pegar o arquivo."
+
+msgid "This chat is empty!"
+msgstr "Esse chat está vazio!"
+
+msgid "Generate file!"
+msgstr "Gerar arquivo!"
+
+msgid "Download file!"
+msgstr "Ba"
+
+msgid "Clean current chat"
+msgstr "Apagar esta conversa"
+
+msgid "View chat history"
+msgstr "Visualizar histórico da conversa"
+
+msgid "Show user profile"
+msgstr "Mostrar perfil do usuário"
+
+msgid "Add this contact to your friends"
+msgstr "Adicionar este contato aos seus amigos"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Adicionar este grupo de chat aos seus favoritos"
+
+msgid "All tabs"
+msgstr "Todas as abas"
+
+msgid "Close this tab"
+msgstr "Fechar esta aba"
+
+msgid "no subject defined for this room."
+msgstr "nenhum assunto definido para esta sala."
+
+msgid "Administration panel for this room"
+msgstr "Painel de administração desta sala"
+
+msgid "Moderators"
+msgstr "Moderadores"
+
+msgid "Participants"
+msgstr "Participantes"
+
+msgid "Visitors"
+msgstr "Visitantes"
+
+msgid "Manage favorite rooms"
+msgstr "Gerenciar salas favoritas"
+
+msgid "Change favorites"
+msgstr "Alterar favoritos"
+
+msgid "Search a room"
+msgstr "Procurar uma sala"
+
+msgid "Select a favorite"
+msgstr "Selecionar um favorito"
+
+msgid "Getting the name..."
+msgstr "Buscando o nome..."
+
+msgid "Gateway"
+msgstr "Gateway"
+
+msgid "Name"
+msgstr "Nome"
+
+msgid "Room"
+msgstr "Sala"
+
+msgid "Add"
+msgstr "Adicionar"
+
+msgid "Edit"
+msgstr "Editar"
+
+msgid "Search a room on"
+msgstr "Procurar uma sala em"
+
+msgid "No room found on this server."
+msgstr "Nenhuma sala encontrada nesse servidor."
+
+msgid "Service discovery"
+msgstr "Descobrir serviços"
+
+msgid "Server to query"
+msgstr "Servidor para pesquisa"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Desculpa, mas a entidade não retornou nenhum resultado!"
+
+msgid "Accounts"
+msgstr "Contas"
+
+msgid "Authentications"
+msgstr "Autenticações"
+
+msgid "Automation"
+msgstr "Automatização"
+
+msgid "Clients"
+msgstr "Clientes"
+
+msgid "Collaboration"
+msgstr "Colaboração"
+
+msgid "Components"
+msgstr "Componentes"
+
+msgid "Rooms"
+msgstr "Salas"
+
+msgid "Directories"
+msgstr "Diretórios"
+
+msgid "Gateways"
+msgstr "Gateways"
+
+msgid "News"
+msgstr "Notícias"
+
+msgid "Hierarchy"
+msgstr "Hierarquia"
+
+msgid "Proxies"
+msgstr "Proxies"
+
+msgid "Publication/Subscription"
+msgstr "Publicação/Subscrição"
+
+msgid "Storage"
+msgstr "Armazenamento"
+
+msgid "Service offline or broken"
+msgstr "Serviço offline ou indisponível"
+
+msgid "Your inbox"
+msgstr "Sua caixa de entrada"
+
+msgid "Available actions"
+msgstr "Ações disponíveis"
+
+msgid "Clean"
+msgstr "Limpar"
+
+msgid "New"
+msgstr "Novo"
+
+msgid "Received"
+msgstr "Recebidos"
+
+msgid "Subject"
+msgstr "Assunto"
+
+msgid "Content"
+msgstr "Conteúdo"
+
+msgid "Send message"
+msgstr "Enviar mensagem"
+
+msgid "Your inbox is empty."
+msgstr "Sua caixa de entrada está vazia."
+
+msgid "MUC administration"
+msgstr "Administração MUC"
+
+msgid "You administrate this room"
+msgstr "Você administra esta sala"
+
+msgid "Enter new subject"
+msgstr "Inserir novo assunto"
+
+msgid "Configuration"
+msgstr "Configuração"
+
+msgid "Authorizations"
+msgstr "Autorizações"
+
+msgid "Member list"
+msgstr "Lista de membros"
+
+msgid "Owner list"
+msgstr "Lista de proprietários"
+
+msgid "Administrator list"
+msgstr "Lista de administradores"
+
+msgid "Outcast list"
+msgstr "Lista de banidos"
+
+msgid "Add an input"
+msgstr "Adicionar uma entrada"
+
+msgid "Destroy this MUC"
+msgstr "Destruir esse MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Sim, vamos lá!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Seu amigo está prestando atenção na conversa."
+
+msgid "Your friend is writing a message..."
+msgstr "Seu amigo está digitando uma mensagem..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Seu amigo parou de escrever uma mensagem."
+
+msgid "Your friend is doing something else."
+msgstr "Seu amigo está fazendo outra coisa."
+
+msgid "Your friend closed the chat."
+msgstr "Seu amigo fechou o chat."
+
+msgid "Requesting this service..."
+msgstr "Requisitando esse serviço..."
+
+msgid "Loading"
+msgstr "Carregando"
+
+msgid "joined the chat room"
+msgstr "entrou na sala de chat"
+
+msgid "left the chat room"
+msgstr "saiu da sala de chat"
+
+msgid "no status"
+msgstr "sem status"
+
+msgid "has been kicked"
+msgstr "foi chutado"
+
+msgid "has been banned"
+msgstr "foi banido"
+
+msgid "no reason"
+msgstr "nenhum motivo"
+
+msgid "Communicate with the entire world!"
+msgstr "Comunique-se com o mundo inteiro!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Permite que você entre em contato com milhões de usuários que utilizam uma rede XMPP como você faz com o Jappix. Entre na comunidade e fique livre."
+
+msgid "Hi there!"
+msgstr "Olá!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr ""
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Acesse sua conta XMPP existente ou crie uma nova de graça!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix é um projeto open-source da PostPro, uma organização sem fins lucrativos que nos oferece uma grande ajuda."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Acesse com sua conta XMPP. Você também pode usar o %s para acessar um grupo de chat."
+
+msgid "Previous"
+msgstr "Anterior"
+
+msgid "General"
+msgstr "Geral"
+
+msgid "Advanced"
+msgstr "Avançado"
+
+msgid "Resource"
+msgstr "Recurso"
+
+msgid "Priority"
+msgstr "Prioridade"
+
+msgid "Low"
+msgstr "Baixa"
+
+msgid "Medium"
+msgstr "Média"
+
+msgid "High"
+msgstr "Alta"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Insira o grupo de chat desejado e o seu apelido. Você também pode voltar para o %s."
+
+msgid "login page"
+msgstr "Página de login"
+
+msgid "Share this link with your friends:"
+msgstr "Compartilhe este link com seus amigos:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Registre uma nova conta XMPP para acessar seus amigos em sua própria rede social. É simples!"
+
+msgid "Required"
+msgstr "Requerido"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Você foi registrado, aqui está seu endereço XMPP:"
+
+msgid "Manager"
+msgstr "Gerenciador"
+
+msgid "Project"
+msgstr "Projeto"
+
+msgid "Encrypted"
+msgstr "Encriptado"
+
+msgid "Unencrypted"
+msgstr "Desencriptado"
+
+msgid "Where are you?"
+msgstr "Onde você está?"
+
+msgid "What's up with you?"
+msgstr "O que você está pensando?"
+
+msgid "Fetching the social channel..."
+msgstr "Buscando o canal social..."
+
+msgid "You are synchronized with your network."
+msgstr "Você está sincronizado com sua rede."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Não é possível enviar: você só pode receber avisos!"
+
+msgid "Media viewer"
+msgstr "Visualizador de media"
+
+msgid "Browse"
+msgstr "Navegar"
+
+msgid "Command"
+msgstr "Comando"
+
+msgid "Subscribe"
+msgstr "Assinar"
+
+msgid "Join"
+msgstr "Entrar"
+
+msgid "Automatic"
+msgstr "Automático"
+
+msgid "Search"
+msgstr "Procurar"
+
+msgid "No result!"
+msgstr "Nenhum resultado!"
+
+msgid "No notifications."
+msgstr "Nenhuma notificação."
+
+msgid "would like to add you as a friend."
+msgstr "gostaria de te adicionar como amigo."
+
+msgid "would like you to join this chatroom:"
+msgstr "gostaria de entrar nesta sala de chat:"
+
+msgid "Do you accept?"
+msgstr "Você aceita?"
+
+msgid "Yes"
+msgstr "Sim"
+
+msgid "No"
+msgstr "Não"
+
+msgid "would like to get authorization."
+msgstr "gostaria de pegar autorização."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Gostaria de ver os amigos %s sugerem você?"
+
+msgid "Submit"
+msgstr "Enviar"
+
+msgid "Client"
+msgstr "Cliente"
+
+msgid "System"
+msgstr "Sistema"
+
+msgid "Local time"
+msgstr "Hora local"
+
+msgid "Comments"
+msgstr "Comentários"
+
+msgid "User profile"
+msgstr "Perfil do usuário"
+
+msgid "See his/her position on the globe"
+msgstr "Visualizar a localização dele/dela"
+
+msgid "Confirm"
+msgstr "Confirmar"
+
+msgid "anonymous mode"
+msgstr "Modo anônimo"
+
+msgid "Groups"
+msgstr "Grupos"
+
+msgid "Unclassified"
+msgstr "Não classificado"
+
+msgid "Authorize"
+msgstr "Autorizar"
+
+msgid "Ask for authorization"
+msgstr "Solicitar autorização"
+
+msgid "Unblock"
+msgstr "Desbloquear"
+
+msgid "Prohibit"
+msgstr "Proibir"
+
+msgid "Block"
+msgstr "Bloquear"
+
+msgid "Chat"
+msgstr "Chat"
+
+msgid "Groupchat"
+msgstr "Grupo de chat"
+
+msgid "Jappix Mobile"
+msgstr "Jappix móvel"
+
+msgid "Desktop"
+msgstr "Desktop"
+
+msgid "Mobile"
+msgstr "Mobile"
+
+msgid "Please wait..."
+msgstr "Aguarde..."
+
+msgid "Please enable JavaScript"
+msgstr "Por favor, habilite JavaScript"
+
+msgid "Your channel"
+msgstr "Seu canal"
+
+msgid "Channel of"
+msgstr "Canal de"
+
+msgid "More notices..."
+msgstr "Mais avisos..."
+
+msgid "Attach a file"
+msgstr "Anexar um arquivo"
+
+msgid "Send"
+msgstr "Enviar"
+
+msgid "Unattach the file"
+msgstr "Desanexar o arquivo"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Um erro ocorreu durante o envio do arquivo: talvez seja grande demais (%s máximo) ou não permitido."
+
+msgid "Authorization failed"
+msgstr "Autorização falhou"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registro falhou, escolhe um nome de usuário diferente"
+
+msgid "Service unavailable"
+msgstr "Serviço indisponível"
+
+msgid "Internal server error, try later"
+msgstr "Erro interno do servidor, tente mais tarde"
+
+msgid "Your form has been sent."
+msgstr "Seu formulário foi enviado."
+
+msgid "Application"
+msgstr "Aplicação"
+
+msgid "XMPP links"
+msgstr "Links XMPP"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Abrir links XMPP com o Jappix"
+
+msgid "changed the subject to:"
+msgstr "Assunto alterado para:"
+
+msgid "Welcome!"
+msgstr "Bem vindo!"
+
+msgid "Friends"
+msgstr "Amigos"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Bem vindo ao Jappix, seu própria rede social!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Antes de começar a utilizar, você terá que alterar algumas configurações, procure por amigos e complete seu perfil."
+
+msgid "Enable notification sounds"
+msgstr "Habilitar som de notificação"
+
+msgid "Share your position on the globe"
+msgstr "Compartilhar sua localização"
+
+msgid "Offline friends"
+msgstr "Amigos offline"
+
+msgid "Don't hide offline friends"
+msgstr "Não esconder amigos offline"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Use esta ferramenta para encontrar seus amigos no servidor que você está utilizando, ou adicione-os mais tarde."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Bom trabalho! Agora você pode compartilhar o Jappix com seus amigos!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Quando você apertar o botão de salvar, o editor de perfil será aberto. Boa socialização!"
+
+msgid "Share Jappix on %s"
+msgstr "Compartilhe o Jappix em %s:"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Usando Jappix, uma plataforma social aberta. Eu sou %s!"
+
+msgid "Unknown name"
+msgstr "Nome desconhecido"
+
+msgid "Unknown country"
+msgstr "País desconhecido"
+
+msgid "Click to enable"
+msgstr "Clique para habilitar"
+
+msgid "Click to disable"
+msgstr "Clique para desabilitar"
+
+msgid "Installation"
+msgstr "Instalação"
+
+msgid "Jappix installation"
+msgstr "Instalação do Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Bem vindo à instalação do Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Essa ferramenta ajudará a agilizar a instalação do Jappix. A primeira plataforma social completa em seu servidor. Você nem precisa conhecimento técnico."
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Vamos dar uma olhada nos passos de instalação:"
+
+msgid "Welcome"
+msgstr "Bem vindo"
+
+msgid "Storage configuration"
+msgstr "Configuração de armazenamento"
+
+msgid "Administrator account"
+msgstr "Conta de administrador"
+
+msgid "Main configuration"
+msgstr "Configuração principal"
+
+msgid "Hosts configuration"
+msgstr "Configuração de hosts"
+
+msgid "Services installation"
+msgstr "Instalação de serviços"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Se o idioma não bate com sua (%1s), você pode fazer o Jappix falar %2s e ficará salvo."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Se você quer alguma ajuda sobre a configuração e instalação do Jappix, você pode usar toda nossa documentação disponível em:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "É hora de criar sua própria rede social: vá para o próximo passo!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix armazena dados constantemente (como arquivos compartilhados, logs de conversa, músicas e de configuração) em uma única pasta segura."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix precisa permissão para escrita nessa pasta. Se não, você precisa ajustar as permissões para %1s ou alterar o proprietário para %2s (dependendo da sua configuração)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Esta pasta possui permissão de escrita, pode continuar!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix oferece a você a possibilidade de gerenciar suas configurações, instalar novos plugins ou procurar por atulizações. Por isso você deve criar um usuário de administração para acessar o gerenciador."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Quando o Jappix for instalado, clique no link do gerenciador, em sua página inicial, para acessá-lo."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Oops, você esqueceu algo ou as duas senhas não conferem."
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix precisa que você especifique alguns valores para funcionar. Corrija as seguintes entradas (ou mantenha as configurações padrões, o que é suficiente para a maioria das pessoas)."
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Note que, se você não especificar um valor obrigatório, ele será automaticamente preenchido com valores padrão."
+
+msgid "User"
+msgstr "Usuário"
+
+msgid "Service"
+msgstr "Serviço"
+
+msgid "Service name"
+msgstr "Nome do serviço"
+
+msgid "Service description"
+msgstr "Descrição do serviço"
+
+msgid "Connection"
+msgstr "Conexão"
+
+msgid "Lock the host"
+msgstr "Veja o endereço"
+
+msgid "Anonymous mode"
+msgstr "Modo anônimo"
+
+msgid "Registration allowed"
+msgstr "Registro permitido"
+
+msgid "Use a proxy"
+msgstr "Usar um proxy"
+
+msgid "Encryption"
+msgstr "Encriptação"
+
+msgid "HTTPS storage"
+msgstr "Armazenamento HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Forçar HTTPS"
+
+msgid "Compression"
+msgstr "Compressão"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Essa página ajuda você a especificar os endereços no qual o Jappix conectará. Você pode deixa-los assim e continuar caso queira usar os endereços dos serviços oficiais."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Talvez você não saiba o que é um servidor BOSH! Na verdade é um transmissor, entre o cliente (Jappix) e um servidor XMPP, necessário devido a limitações técnicas."
+
+msgid "Main host"
+msgstr "Endereço principal"
+
+msgid "Groupchat host"
+msgstr "Endereço dos grupos de chat"
+
+msgid "Anonymous host"
+msgstr "Endereço do modo anônimo"
+
+msgid "Directory host"
+msgstr "Endereço do diretório"
+
+msgid "BOSH host"
+msgstr "Endereço do BOSH"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Você pode instalar programas extras em seu servidor para estender as funcionalidades do Jappix. Outros podem ser modificados por causa de restrições de segurança definidas por padrão."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Para executar isso, você precisa ter acesso shell ao servidor e logar como root. Lembre-se, esta opções é facultativa. Jappix funcionará sem esses módulos, mas algumas de suas funções ficarão indisponíveis."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Após terminar a instalação, Jappix vai gerar os arquivos de cache. Isso pode demorar um pouco. Espere até que a aplicação termine."
+
+msgid "Thanks for using Jappix!"
+msgstr "Obrigado por utilizar Jappix!"
+
+msgid "Next"
+msgstr "Próximo"
+
+msgid "Finish"
+msgstr "Terminar"
+
+msgid "Check again"
+msgstr "Checar novamente"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "A pasta não tem permissão de escrita, aplique as permissões corretas à pasta %s."
+
+msgid "%s is installed on your system."
+msgstr "%s está instalado no seu sistema."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s não está instalado em seu sistema, você deve instalar %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP - maximum_upload_size é suficiente (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP - maximum_upload_size não é suficiente (%1s), você deve alterar para %2s em %3s."
+
+msgid "Jappix manager"
+msgstr "Gerenciador do Jappix"
+
+msgid "Manager access"
+msgstr "Acesso ao gerenciador"
+
+msgid "Statistics"
+msgstr "Estatísticas"
+
+msgid "Hosts"
+msgstr "Endereços"
+
+msgid "Design"
+msgstr "Design"
+
+msgid "Repeat"
+msgstr "Repetir"
+
+msgid "All"
+msgstr "Todos"
+
+msgid "Horizontal"
+msgstr "Horizontal"
+
+msgid "Vertical"
+msgstr "Vertical"
+
+msgid "Center"
+msgstr "Centralizado"
+
+msgid "Left"
+msgstr "Esquerda"
+
+msgid "Right"
+msgstr "Direita"
+
+msgid "Top"
+msgstr "Topo"
+
+msgid "Bottom"
+msgstr "Fundo"
+
+msgid "Adapt"
+msgstr "Adaptar"
+
+msgid "Color"
+msgstr "Cor"
+
+msgid "Users"
+msgstr "Usuários"
+
+msgid "Updates"
+msgstr "Atualizações"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Esta é uma área restrita: apenas usuários autorizados podem gerenciar este Jappix."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Utilize o formulário abaixo para acessar o painel de administração."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Para melhorar a segurança, as seções são limitadas em tempo, e, quando seu navegador for fechado, você será desconectado."
+
+msgid "Credentials"
+msgstr "Credenciais"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Você foi desconectado. Tchau!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Opps, você não foi reconhecido como um administrador válido. Verifique suas credenciais!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Estatísticas básicas sobre coisas importantes são processadas pelo Jappix, você pode encontra-las abaixo."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Altere as configurações do Jappix com esta ferramenta."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Altere os endereços XMPP que este Jappix fornece com esta ferramenta."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Todos os arquivos armazenados por esse Jappix podem ser gerenciados com esta ferramenta: selecione uma sub-pasta e comece a editar seu conteúdo!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix é totalmente customizável: você pode alterar seu design bem aqui."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Esta não é uma imagem válida, use somente PNG, GIF ou JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "A imagem não pôde ser recebida, se importa de enviar novamente?"
+
+msgid "Your image was added to the list!"
+msgstr "A sua imagem foi adicionada à lista!"
+
+msgid "Changes saved!"
+msgstr "Alterações salvas!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Você pode definir mais de um administrador para este Jappix. Você também pode alterar uma senha com essa ferramenta. "
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Atualize seu Jappix com essa ferramenta ou cheque se há atualizações. Informações sobre novas versões serão mostradas (em inglês)."
+
+msgid "Access statistics"
+msgstr "Estatísticas de acesso"
+
+msgid "Share statistics"
+msgstr "Estatísticas de compartilhamento"
+
+msgid "Other statistics"
+msgstr "Outras estatísticas"
+
+msgid "January"
+msgstr "Janeiro"
+
+msgid "February"
+msgstr "Fevereiro"
+
+msgid "March"
+msgstr "Março"
+
+msgid "April"
+msgstr "Abril"
+
+msgid "May"
+msgstr "Maio"
+
+msgid "June"
+msgstr "Junho"
+
+msgid "July"
+msgstr "Julho"
+
+msgid "August"
+msgstr "Agosto"
+
+msgid "September"
+msgstr "Setembro"
+
+msgid "October"
+msgstr "Outubro"
+
+msgid "November"
+msgstr "Novembro"
+
+msgid "December"
+msgstr "Dezembro"
+
+msgid "Monday"
+msgstr "Segunda-feira"
+
+msgid "Tuesday"
+msgstr "Terça-feira"
+
+msgid "Wednesday"
+msgstr "Quarta-feira"
+
+msgid "Thursday"
+msgstr "Quinta-feira"
+
+msgid "Friday"
+msgstr "Sexta-feira"
+
+msgid "Saturday"
+msgstr "Sábado"
+
+msgid "Sunday"
+msgstr "Domingo"
+
+msgid "Total"
+msgstr "Total"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Logs"
+
+msgid "Music"
+msgstr "Música"
+
+msgid "Backgrounds"
+msgstr "Papéis de parede"
+
+msgid "Share"
+msgstr "Compartilhar"
+
+msgid "Background"
+msgstr "Papel de parede"
+
+msgid "Notice"
+msgstr "Aviso"
+
+msgid "Your design preferences have been saved!"
+msgstr "Suas preferências de design foram salvas!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Cheque suas entradas: alguma coisa está faltando!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Altere o papel de parede do seu Jappix. Você também pode inserir uma cor ou enviar uma imagem. Deixe sua criatividade fluir!"
+
+msgid "Use default background"
+msgstr "Usar papel de parede padrão"
+
+msgid "Use your own image"
+msgstr "Usar sua própria imagem"
+
+msgid "Select a background to use and change the display options."
+msgstr "Selecione um papel de parede e altere as opções de exibição."
+
+msgid "Use your own color"
+msgstr "Usar sua própria cor"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Digite código hexadecimal da cor deseja para usar como papel de parede."
+
+msgid "Manage backgrounds"
+msgstr "Gerenciar papéis de parede"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Você pode adicionar um novo papel de parede para a lista com essa ferramenta. Envie uma imagem válida."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Se você quiser remover alguma imagem, use o navegador abaixo."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Defina um aviso na tela inicial para todos os usuários, como uma mensagem importante ou uma advertência."
+
+msgid "Simple notice"
+msgstr "Aviso simples"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Esse aviso precisa apenas de texto simple para aparecer, nenhum código é permitido!"
+
+msgid "Advanced notice"
+msgstr "Aviso avançado"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Você pode customizar seu aviso com código HTML, CSS e Javascript."
+
+msgid "Available updates"
+msgstr "Atualizações disponíveis."
+
+msgid "What's new?"
+msgstr "O que há de novo?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Suas pastas de armazenamento não estão com permissão de escrita, aplique as permissões!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s pode estar causando problemas com o proxy, aumente o valor de %2s para %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Você está utilizando uma versão de desenvolvimento do Jappix. Atualize-a através do nosso repositório executando: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Uma nova atualização do Jappix está disponível! Cheque o que há de novo e execute a atualização!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Sua versão está desatualizada. Atualiza agora para %s clicando aqui!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Sua versão parece estar atualizada, mas você pode checar atualizações manualmente clicando aqui."
+
+msgid "Check for updates"
+msgstr "Checar por atualizações"
+
+msgid "Update in progress"
+msgstr "Atualização em progresso"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix foi atualizado: você agora está rodando a última versão. Aproveite!"
+
+msgid "The update has failed! Please try again later."
+msgstr "A atualização falhou! Tente novamente depois."
+
+msgid "Downloading package..."
+msgstr "Baixando pacote..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Removendo atuais arquivos de sistema do Jappix..."
+
+msgid "Extracting package..."
+msgstr "Extraindo pacote..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Regerando árvore de pastas de armazenamento..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix agora está atualizado!"
+
+msgid "Aborted: socket error!"
+msgstr "Abortado: erro de soquete!"
+
+msgid "Aborted: buffer error!"
+msgstr "Abortado: erro de buffer!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Abortado: tudo sem permissão de escrita!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Abortado: não foi possível extrair o pacote!"
+
+msgid "Visits"
+msgstr "Visitas"
+
+msgid "Daily"
+msgstr "Diariamente"
+
+msgid "Weekly"
+msgstr "Semanalmente"
+
+msgid "Monthly"
+msgstr "Mensalmente"
+
+msgid "Yearly"
+msgstr "Anualmente"
+
+msgid "Size"
+msgstr "Tamanho"
+
+msgid "Clean everything"
+msgstr "Apagar tudo"
+
+msgid "Purge cache"
+msgstr "Eliminar cache"
+
+msgid "Purge logs"
+msgstr "Eliminar logs"
+
+msgid "Purge updates"
+msgstr "Eliminar atualizações"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "A pasta de armazenamento foi esvaziada!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Mantenha seu Jappix limpo e rápido, apague as pastas de armazenamento regularmente!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Envie suas músicas (Ogg Vorbis, MP3 ou WAV) para ouvi-las no Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "O arquivo que você quer enviar deve ser menor do que %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Fique sabendo o que os seus usuários armazenam em seu servidor e remova os conteúdos indesejados."
+
+msgid "Title"
+msgstr "Título"
+
+msgid "Artist"
+msgstr "Artistas"
+
+msgid "Album"
+msgstr "Álbum"
+
+msgid "File"
+msgstr "Arquivo"
+
+msgid "Upload"
+msgstr "Envio"
+
+msgid "The folder is empty."
+msgstr "A pasta está vazia."
+
+msgid "The music could not be received, please retry!"
+msgstr "A música não pôde ser recebida, tente novamente!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Esse não é um arquivo de música válido, envie apenas Ogg Vorbis, MP3 ou WAV!"
+
+msgid "Your music has been added!"
+msgstr "Sua música foi adicionada!"
+
+msgid "The selected elements have been removed."
+msgstr "Os elementos selecionados foram removidos."
+
+msgid "You must select elements to remove!"
+msgstr "Você precisa selecionar os elementos para remover!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Adicione um novo usuário ou troque uma senha (digite o nome de um usuário), com esta ferramenta. Envie uma senha difícil!"
+
+msgid "Manage"
+msgstr "Gerenciar"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Remova usuários com esta ferramenta. Você não pode remover um usuário caso ele seja o único."
+
+msgid "The user has been added!"
+msgstr "O usuário foi adicionado!"
+
+msgid "The chosen users have been removed."
+msgstr "O usuário selecionado foi removido."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Você precisa selecionar um ou mais usuários para remover!"
+
+msgid "Yesterday"
+msgstr "Ontem"
+
+msgid "%s days ago"
+msgstr "%s dias atrás"
+
+msgid "User currently active"
+msgstr "Usuário ativo"
+
+msgid "Last seen: %s"
+msgstr "Visto em: %s"
+
+msgid "Inactive since: %s"
+msgstr "Inativo desde: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Seu amigo parece não ter recebido sua(s) mensagem(ns)!"
+
+msgid "Static content server"
+msgstr "Servidor de conteúdo estático"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Esse é o servidor de conteúdo estático para %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Amigos sugeridos"
+
+msgid "Check all"
+msgstr "Marcar todos"
+
+msgid "Uncheck all"
+msgstr "Desmarcar todos"
+
+msgid "Choose"
+msgstr "Escolher"
+
+msgid "List name"
+msgstr "Nome da lista"
+
+msgid "Allow"
+msgstr "Permitir"
+
+msgid "Deny"
+msgstr "Recusar"
+
+msgid "Group"
+msgstr "Grupo"
+
+msgid "Subscription"
+msgstr "Subscrição"
+
+msgid "Both"
+msgstr "Ambos"
+
+msgid "From"
+msgstr "De"
+
+msgid "Everybody"
+msgstr "Todo mundo"
+
+msgid "Send messages"
+msgstr "Enviar mensagens"
+
+msgid "Send queries"
+msgstr "Enviar consultas"
+
+msgid "See my status"
+msgstr "Ver meu status"
+
+msgid "Send his/her status"
+msgstr "Enviar status dele/dela"
+
+msgid "Everything"
+msgstr "Tudo"
+
+msgid "Item"
+msgstr "Item"
+
+msgid "Order"
+msgstr "Ordem"
+
+msgid "Active for this session"
+msgstr "Ativos nessa sessão"
+
+msgid "Always active"
+msgstr "Sempre ativo"
+
+msgid "User directory"
+msgstr "Diretório de usuário"
+
+msgid "Search a friend"
+msgstr "Procurar um amigo"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "A ferramenta solicitada não está implementada pelo servidor e por isso não pode ser processada."
+
+msgid "This is a repeat from %s"
+msgstr "Essa é uma repetição de %s"
+
+msgid "Loading comments..."
+msgstr "Carregando comentários..."
+
+msgid "Type your comment here..."
+msgstr "Escreva seu comentário aqui..."
+
+msgid "Could not get the comments!"
+msgstr "Não foi possível buscar os comentários!"
+
+msgid "Show comments"
+msgstr "Mostrar comentários"
+
+msgid "Send him/her a message"
+msgstr "Envie uma mensagem para ele/ela"
+
+msgid "Start a chat with him/her"
+msgstr "Comece um chat com ele/ela"
+
+msgid "Media integration"
+msgstr "Integração de media"
+
+msgid "Comments locked!"
+msgstr "Comentários bloqueados!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Escreva algo que você queira compartilhar com seus amigos..."
+
+msgid "changed his/her nickname to %s"
+msgstr "Alterado o apelido dele/dela para %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "Comentado um ítem que você segue: “%s”."
+
+msgid "Hide"
+msgstr "Esconder"
+
+msgid "liked your post: “%s”."
+msgstr "Gostou do seu post: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "Mencionou você em algum lugar: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "publicou em seu mural: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "marcou você numa foto (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "marcou você em um vídeo (%s)."
+
+msgid "Show"
+msgstr "Mostrar"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Precisa de ajuda? É melhor você ler nossa página de documentação sobre como preencher este formulário!"
+
+msgid "Pubsub host"
+msgstr "Endereço Pubsub"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix é uma ótima plataforma social que você pode acessar de onde estiver, quando quiser e comunicar-se com quem quiser."
+
+msgid "Manager link"
+msgstr "Link do gerenciador"
+
+msgid "User uploads server"
+msgstr "Servidor de envio dos usuários"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Esse é o servidor de envio dos usuários para %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Logo"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Você pode definir sua própria logo no lugar da padrão. Tome cuidado com o tamanho e as cores de cada logo!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Envie cada logo do tamanho de pixels recomendado."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Esta não é uma imagem válida, envie somente no formato PNG!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Sua logo foi alterada com sucesso!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "O formato da sua logo deve ser PNG. Deixe o campo em branco que a logo não será alterada."
+
+msgid "Remove this logo"
+msgstr "Remover essa logo"
+
+msgid "View this logo"
+msgstr "Visualizar essa logo"
+
+msgid "Send a file"
+msgstr "Enviar um arquivo"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "Quando enviado seu amigo será avisado para baixar o arquivo."
+
+msgid "Groupchats to join"
+msgstr "Grupos de chat para entrar"
+
+msgid "Purge sent files"
+msgstr "Eliminar arquivos enviados"
+
+msgid "would like to send you a file: “%s”."
+msgstr "gostaria de te enviar um arquivo: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "aceitou receber seu arquivo: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "negou receber seu arquivo: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "não conseguiu receber seu arquivo: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "recebeu uma solicitação de troca de arquivos: “%s”."
+
+msgid "Available shortcuts:"
+msgstr "Atalhos disponíveis"
+
+msgid "%s removes the chat logs"
+msgstr "%s remove os logs de chat"
+
+msgid "%s joins a groupchat"
+msgstr "%s entra em um grupo de chat"
+
+msgid "%s closes the chat"
+msgstr "%s fecha o chat"
+
+msgid "%s shows the user profile"
+msgstr "%s mostra o perfil do usuário"
+
+msgid "%s sends a message to the room"
+msgstr "%s envia uma mensagem para a sala"
+
+msgid "%s changes your nickname"
+msgstr "%s altera seu apelido"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s envia uma mensagem para alguém na sala"
+
+msgid "%s changes the room topic"
+msgstr "%s altera o tópico da sala"
+
+msgid "%s kicks an user of the room"
+msgstr "%s chuta um usuário da sala"
+
+msgid "%s bans an user of the room"
+msgstr "%s bane um usuário da sala"
+
+msgid "%s invites someone to join the room"
+msgstr "%s convida alguém para entrar na sala"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/ru/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/ru/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..e28ee04
Binary files /dev/null and b/jappixmini/jappix/lang/ru/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/ru/LC_MESSAGES/main.po b/jappixmini/jappix/lang/ru/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..88b4a2d
--- /dev/null
@@ -0,0 +1,1870 @@
+# Russian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:47+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "JavaScript отключен в вашем браузере, без него Jappix не может работать!"
+
+msgid "An open social network"
+msgstr "Открытая социальная сеть"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Работа с Jappix прервана из-за проблем со связью, ошибки или неверных регистрационных данных (проверьте имя и пароль), просим прощения за неудобства."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Невозможно получить спискок содержимого этого сервера."
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Пароль изменен. Вы можете войти с новым паролем."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Ваш XMPP аккаунт был удален, до скорой встречи!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Вы покинули свою учетную запись XMPP, удачного дня!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Вы пытаетесь войти в несуществующую комнату. Можно попытаться создать её!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Комната была удалена, теперь кто-то другой сможет создать её ещё раз."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Нужного вам пользователя здесь нет."
+
+msgid "Please enter the group chat address to join."
+msgstr "Пожалуйста, введите адрес группового чата чтоб присоединиться."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Введите свое прозвище, чтобы присоединиться к %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Комната (%s) защищена паролем."
+
+msgid "Your browser is out of date!"
+msgstr "Ваш браузер устарел, пожалуйста обновите!"
+
+msgid "Last %s version is better!"
+msgstr "Свежая версия %s - лучше!"
+
+msgid "Login"
+msgstr "Войти"
+
+msgid "Register"
+msgstr "Регистрация"
+
+msgid "Here we go!"
+msgstr "Поехали!"
+
+msgid "Server"
+msgstr "Сервер"
+
+msgid "Password"
+msgstr "Пароль"
+
+msgid "Remember me"
+msgstr "Запомнить меня"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Этот инструмент был заблокирован, вы не можете его использовать!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Из-за неполадок в сети вы разъединились. Что теперь хотите сделать?"
+
+msgid "Reconnect"
+msgstr "Переподключение"
+
+msgid "Messages"
+msgstr "Сообщения"
+
+msgid "Profile"
+msgstr "Профиль"
+
+msgid "Options"
+msgstr "Настройки"
+
+msgid "Disconnect"
+msgstr "Выход"
+
+msgid "Filter"
+msgstr "Фильтр"
+
+msgid "Add a friend"
+msgstr "Добавить друга"
+
+msgid "Your groupchats"
+msgstr "Ваша группа"
+
+msgid "Manage your favorite groupchats"
+msgstr "Управлять списком Ваших любимых комнат."
+
+msgid "More stuff"
+msgstr "Дополнительно"
+
+msgid "Show all friends"
+msgstr "Показать всех"
+
+msgid "Only show connected friends"
+msgstr "Показать лишь подключенных"
+
+msgid "Message archives"
+msgstr "Архив сообщений"
+
+msgid "Date"
+msgstr "Дата"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Выберите историю общения с кем хотите увидеть."
+
+msgid "Nothing found for: %s"
+msgstr "Для %s ничего не найдено"
+
+msgid "A short message?"
+msgstr "Статусное сообщение?"
+
+msgid "How are you?"
+msgstr "Как дела?"
+
+msgid "What are you doing?"
+msgstr "Чем вы сейчас заняты?"
+
+msgid "Join a chat"
+msgstr "Поговорить"
+
+msgid "Status"
+msgstr "Состояние"
+
+msgid "Available"
+msgstr "Доступен"
+
+msgid "Talkative"
+msgstr "Готов поболтать"
+
+msgid "Away"
+msgstr "Отошел"
+
+msgid "Not available"
+msgstr "Недоступен"
+
+msgid "Busy"
+msgstr "Занят"
+
+msgid "Mood"
+msgstr "Настроение"
+
+msgid "None"
+msgstr "Ничего"
+
+msgid "Crazy"
+msgstr "Сумасшедший"
+
+msgid "Excited"
+msgstr "Взволнованный"
+
+msgid "Playful"
+msgstr "Игривый"
+
+msgid "Happy"
+msgstr "Счастливый"
+
+msgid "Shocked"
+msgstr "Шокирован"
+
+msgid "Hot"
+msgstr "Страстный"
+
+msgid "Sad"
+msgstr "Грустный"
+
+msgid "Amorous"
+msgstr "Влюблённый"
+
+msgid "Confident"
+msgstr "Самоуверенный"
+
+msgid "Activity"
+msgstr "Деятельность"
+
+msgid "Chores"
+msgstr "Дела домашние"
+
+msgid "Drinking"
+msgstr "Пью"
+
+msgid "Eating"
+msgstr "Кушаю"
+
+msgid "Exercising"
+msgstr "Осуществление"
+
+msgid "Grooming"
+msgstr "Забота"
+
+msgid "Appointment"
+msgstr "Должность"
+
+msgid "Inactive"
+msgstr "Неактивный"
+
+msgid "Relaxing"
+msgstr "Расслабляюсь"
+
+msgid "Talking"
+msgstr "Болтаю"
+
+msgid "Traveling"
+msgstr "Путешествую"
+
+msgid "Working"
+msgstr "Работаю"
+
+msgid "View profile"
+msgstr "Показать профиль"
+
+msgid "Repeat this notice"
+msgstr "Повторить уведомление"
+
+msgid "Remove this notice"
+msgstr "Удалить уведомление"
+
+msgid "Your profile"
+msgstr "Ваш профиль"
+
+msgid "Identity"
+msgstr "Подлинность"
+
+msgid "Profile image"
+msgstr "Аватар"
+
+msgid "Others"
+msgstr "Другие"
+
+msgid "Personal"
+msgstr "Персональные данные"
+
+msgid "Complete name"
+msgstr "Полное имя"
+
+msgid "Nickname"
+msgstr "Псевдоним"
+
+msgid "First name"
+msgstr "Имя"
+
+msgid "Last name"
+msgstr "Фамилия"
+
+msgid "Date of birth"
+msgstr "Дата рождения"
+
+msgid "Contact"
+msgstr "Контакт"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Телефон"
+
+msgid "Website"
+msgstr "Веб-сайт"
+
+msgid "Current"
+msgstr "Текущий"
+
+msgid "Delete"
+msgstr "Удалить"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Какая жалость! У вас нет аватара"
+
+msgid "Address"
+msgstr "Адрес"
+
+msgid "Street"
+msgstr "Улица"
+
+msgid "City"
+msgstr "Город"
+
+msgid "Postal code"
+msgstr "Индекс"
+
+msgid "Country"
+msgstr "Страна"
+
+msgid "Biography"
+msgstr "Биография"
+
+msgid "Important notice"
+msgstr "Важное сообщение"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Будьте осторожны с информацией которую вы пишете в вашем профиле, потому что это доступно каждому."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Не вся информация приватна на XMPP, одна из тех вещей - ваш профиль."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "Сохранить"
+
+msgid "Cancel"
+msgstr "Отмена"
+
+msgid "Edit options"
+msgstr "Редактировать настройки"
+
+msgid "Channel"
+msgstr "Канал"
+
+msgid "Commands"
+msgstr "Комманды"
+
+msgid "Sounds"
+msgstr "Звуки"
+
+msgid "Privacy"
+msgstr "Приватность"
+
+msgid "Message archiving"
+msgstr "Архив сообщений"
+
+msgid "Store a history of your chats"
+msgstr "Сохранять историю разговоров"
+
+msgid "Geolocation"
+msgstr "Местоположение"
+
+msgid "Empty"
+msgstr "Освободить"
+
+msgid "Empty channel"
+msgstr "Пустая конференция"
+
+msgid "Persistent"
+msgstr "Постоянный"
+
+msgid "Maximum notices"
+msgstr "Максимальное число уведомлений"
+
+msgid "Account"
+msgstr "Учетная запись"
+
+msgid "Change password"
+msgstr "Изменить пароль"
+
+msgid "Delete account"
+msgstr "Удалить акаунт"
+
+msgid "Old"
+msgstr "Старый"
+
+msgid "New (2 times)"
+msgstr "Новый"
+
+msgid "Continue"
+msgstr "Продолжить"
+
+msgid "To"
+msgstr "К"
+
+msgid "Close"
+msgstr "Закрыть"
+
+msgid "unknown"
+msgstr "неизвестно"
+
+msgid "Unavailable"
+msgstr "Недоступен"
+
+msgid "is now"
+msgstr "в настоящее время"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Подождите, аватар загружается..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Вот он! Новый аватар."
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Этот файл не поддерживается или имеет плохой размер."
+
+msgid "Reply"
+msgstr "Ответить"
+
+msgid "Error"
+msgstr "Ошибка"
+
+msgid "Click here to solve the error"
+msgstr "Кликни, чтоб устранить ошибку"
+
+msgid "You"
+msgstr "Ты"
+
+msgid "Remove"
+msgstr "Удалить"
+
+msgid "Rename"
+msgstr "Переименовать"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Привет, я %s. Хочю добавить тебя в друзья."
+
+msgid "Smiley insertion"
+msgstr "Добавить смайлик"
+
+msgid "Change style"
+msgstr "Изменить стиль"
+
+msgid "Text in bold"
+msgstr "Жирный"
+
+msgid "Text in italic"
+msgstr "Курсив"
+
+msgid "Underlined text"
+msgstr "Подчеркнуто"
+
+msgid "Save chat"
+msgstr "Сохранить беседу"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Щелкните на следующей ссылке чтобы получить журнал разговора и подождите. Потом опять щелкните для получения файла."
+
+msgid "This chat is empty!"
+msgstr "Этот чат пуст!"
+
+msgid "Generate file!"
+msgstr "Создать файл!"
+
+msgid "Download file!"
+msgstr "Скачать файл!"
+
+msgid "Clean current chat"
+msgstr "Очистить текущий чат"
+
+msgid "View chat history"
+msgstr "Просмотр истории разговора"
+
+msgid "Show user profile"
+msgstr "Показать профиль пользователя"
+
+msgid "Add this contact to your friends"
+msgstr "Добавить этого пользователя в друзья"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Добавить эту конференцию в избранные"
+
+msgid "All tabs"
+msgstr "Все вкладки"
+
+msgid "Close this tab"
+msgstr "Закрить эту вкладку"
+
+msgid "no subject defined for this room."
+msgstr "для данной комнаты тема не была установлена."
+
+msgid "Administration panel for this room"
+msgstr "Панель администрирования для етой комнаты"
+
+msgid "Moderators"
+msgstr "Модераторы"
+
+msgid "Participants"
+msgstr "Участники"
+
+msgid "Visitors"
+msgstr "Посетители"
+
+msgid "Manage favorite rooms"
+msgstr "Управление избранни комнатами"
+
+msgid "Change favorites"
+msgstr "изменить избранние"
+
+msgid "Search a room"
+msgstr "Найти комнату"
+
+msgid "Select a favorite"
+msgstr "Добавить в избраннное"
+
+msgid "Getting the name..."
+msgstr "Получение имени..."
+
+msgid "Gateway"
+msgstr "Маршрутизатор"
+
+msgid "Name"
+msgstr "Имя"
+
+msgid "Room"
+msgstr "Комната"
+
+msgid "Add"
+msgstr "Добавить"
+
+msgid "Edit"
+msgstr "Изменить"
+
+msgid "Search a room on"
+msgstr "Найти комнату на"
+
+msgid "No room found on this server."
+msgstr "Комнат на сервере не найдено."
+
+msgid "Service discovery"
+msgstr "Обзор сервисов"
+
+msgid "Server to query"
+msgstr "Запрос к серверу"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Сожалею, но объект не ответил на запрос!"
+
+msgid "Accounts"
+msgstr "Учетные записи"
+
+msgid "Authentications"
+msgstr "Аутентификация"
+
+msgid "Automation"
+msgstr "Автоматизация"
+
+msgid "Clients"
+msgstr "Клиенты"
+
+msgid "Collaboration"
+msgstr "Сотрудничество"
+
+msgid "Components"
+msgstr "Компоненты"
+
+msgid "Rooms"
+msgstr "Комнаты"
+
+msgid "Directories"
+msgstr "Директории"
+
+msgid "Gateways"
+msgstr "Шлюзы"
+
+msgid "News"
+msgstr "Новости"
+
+msgid "Hierarchy"
+msgstr "Иерархия"
+
+msgid "Proxies"
+msgstr "Прокси"
+
+msgid "Publication/Subscription"
+msgstr "Публикация/Подписка"
+
+msgid "Storage"
+msgstr "Хранилище"
+
+msgid "Service offline or broken"
+msgstr "Сервис недоступен"
+
+msgid "Your inbox"
+msgstr "Входящие"
+
+msgid "Available actions"
+msgstr "Доступные действия"
+
+msgid "Clean"
+msgstr "Очистить"
+
+msgid "New"
+msgstr "Новый"
+
+msgid "Received"
+msgstr "Принятый"
+
+msgid "Subject"
+msgstr "Тема"
+
+msgid "Content"
+msgstr "Содержимое"
+
+msgid "Send message"
+msgstr "Отправит сообщение"
+
+msgid "Your inbox is empty."
+msgstr "У вас нет сообщений"
+
+msgid "MUC administration"
+msgstr "Администрирование многопользовательской конференции"
+
+msgid "You administrate this room"
+msgstr "Вы администратор этой комнаты"
+
+msgid "Enter new subject"
+msgstr "Введите тему"
+
+msgid "Configuration"
+msgstr "Установки"
+
+msgid "Authorizations"
+msgstr "Авторизация"
+
+msgid "Member list"
+msgstr "Участники"
+
+msgid "Owner list"
+msgstr "Список владельцев"
+
+msgid "Administrator list"
+msgstr "Список администраторов"
+
+msgid "Outcast list"
+msgstr "Отклонённые"
+
+msgid "Add an input"
+msgstr "Добавить вход"
+
+msgid "Destroy this MUC"
+msgstr "Уничтожить эту комнату"
+
+msgid "Yes, let's do it!"
+msgstr "Да, давайте сделаем это!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Ваш друг обращает внимание на беседу."
+
+msgid "Your friend is writing a message..."
+msgstr "Ваш друг пишет сообщение..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Ваш друг прекратил написание сообщения."
+
+msgid "Your friend is doing something else."
+msgstr "Ваш друг делает что-то ещё."
+
+msgid "Your friend closed the chat."
+msgstr "Ваш друг закрыл окно чата."
+
+msgid "Requesting this service..."
+msgstr "Запрос сервиса..."
+
+msgid "Loading"
+msgstr "Загрузка"
+
+msgid "joined the chat room"
+msgstr "присоединится к комнате"
+
+msgid "left the chat room"
+msgstr "покинул комнату"
+
+msgid "no status"
+msgstr "нет статуса"
+
+msgid "has been kicked"
+msgstr "был выставлен"
+
+msgid "has been banned"
+msgstr "был забанен"
+
+msgid "no reason"
+msgstr "нет причины"
+
+msgid "Communicate with the entire world!"
+msgstr "Общайся со всем миром!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Это позволит общаться с миллионами пользователей Jappix, как и вы, использующих XMPP. Войди в сообщество и почувствуй свободу!"
+
+msgid "Hi there!"
+msgstr "Приветствуем здесь!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Добро пожаловать в %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Ввойдите в ваш XMPP аккаунт или создайте новый бесплатно!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix - это открытый проект от PostPro, некоммерческой организации, обеспечивающей нам отличную поддержу"
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Ввойдите в ваш XMPP аккаунт. Также можете использовать %s для присоединения к общей беседе."
+
+msgid "Previous"
+msgstr "Предыдущий"
+
+msgid "General"
+msgstr "Основные"
+
+msgid "Advanced"
+msgstr "Дополнительно"
+
+msgid "Resource"
+msgstr "Ресурс"
+
+msgid "Priority"
+msgstr "Приоритет"
+
+msgid "Low"
+msgstr "Низкий"
+
+msgid "Medium"
+msgstr "Средний"
+
+msgid "High"
+msgstr "Высокий"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Введите название конференции и ник. (Вы можете вернуться к %s)."
+
+msgid "login page"
+msgstr "Страница входа"
+
+msgid "Share this link with your friends:"
+msgstr "Поделитесь ссылкой с друзьями:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Зарегистрируйте новый XMPP-аккаунт чтобы подключиться к сети друзей. Это просто!"
+
+msgid "Required"
+msgstr "Обязательный"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Вы были зарегистрированы, ваш XMPP-адрес:"
+
+msgid "Manager"
+msgstr "Менеджер"
+
+msgid "Project"
+msgstr "Проект"
+
+msgid "Encrypted"
+msgstr "Зашифрованный"
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr "Где ты?"
+
+msgid "What's up with you?"
+msgstr "Что с тобой?"
+
+msgid "Fetching the social channel..."
+msgstr "Вход в социальный канал..."
+
+msgid "You are synchronized with your network."
+msgstr "Вы синхронизированы с сетью."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Не может быть отправлено: вы можете только получать уведомления!"
+
+msgid "Media viewer"
+msgstr "Медиа менеджер"
+
+msgid "Browse"
+msgstr "Просмотр"
+
+msgid "Command"
+msgstr "Команда"
+
+msgid "Subscribe"
+msgstr "Подписаться"
+
+msgid "Join"
+msgstr "Войти"
+
+msgid "Automatic"
+msgstr "Автоматически"
+
+msgid "Search"
+msgstr "Поиск"
+
+msgid "No result!"
+msgstr "Нет результата!"
+
+msgid "No notifications."
+msgstr "Нет уведомлений."
+
+msgid "would like to add you as a friend."
+msgstr "добавить себя как друга."
+
+msgid "would like you to join this chatroom:"
+msgstr "хотели бы присоединиться к чату:"
+
+msgid "Do you accept?"
+msgstr "Вы принимаете?"
+
+msgid "Yes"
+msgstr "Да"
+
+msgid "No"
+msgstr "Нет"
+
+msgid "would like to get authorization."
+msgstr "хочет получит авторизацию"
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Хотите ли видеть предложенных вам %s друзей?"
+
+msgid "Submit"
+msgstr "Отправить"
+
+msgid "Client"
+msgstr "Клиент"
+
+msgid "System"
+msgstr "Система"
+
+msgid "Local time"
+msgstr "Местное время"
+
+msgid "Comments"
+msgstr "Комментарии"
+
+msgid "User profile"
+msgstr "Профиль пользователя"
+
+msgid "See his/her position on the globe"
+msgstr "Посмотреть географическое положение"
+
+msgid "Confirm"
+msgstr "Подтвердить"
+
+msgid "anonymous mode"
+msgstr "анонимный режим"
+
+msgid "Groups"
+msgstr "Группы"
+
+msgid "Unclassified"
+msgstr "Неизвестно"
+
+msgid "Authorize"
+msgstr "Авторизовать"
+
+msgid "Ask for authorization"
+msgstr "Запросить подписку"
+
+msgid "Unblock"
+msgstr "Разблокировать"
+
+msgid "Prohibit"
+msgstr "Запретить"
+
+msgid "Block"
+msgstr "Блокировать"
+
+msgid "Chat"
+msgstr "Чат"
+
+msgid "Groupchat"
+msgstr "Чат"
+
+msgid "Jappix Mobile"
+msgstr "Мобильный Jappix"
+
+msgid "Desktop"
+msgstr "Полная версия"
+
+msgid "Mobile"
+msgstr "Мобильный"
+
+msgid "Please wait..."
+msgstr "Пожалуйста, подождите..."
+
+msgid "Please enable JavaScript"
+msgstr "Пожалуйста, включите JavaScript"
+
+msgid "Your channel"
+msgstr "Ваш канал"
+
+msgid "Channel of"
+msgstr "Канал"
+
+msgid "More notices..."
+msgstr "Другие уведомления..."
+
+msgid "Attach a file"
+msgstr "Присоединить файл"
+
+msgid "Send"
+msgstr "Отправить"
+
+msgid "Unattach the file"
+msgstr "Удалить файл"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "При выгрузке вашего файла произошла ошибка: может он слишком велик (%s maximum) или его формат запрещен!"
+
+msgid "Authorization failed"
+msgstr "Ошибка аутентификации"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Ошибка регистрации. Пожалуйста, выберите другое имя пользователя"
+
+msgid "Service unavailable"
+msgstr "Сервис недоступен"
+
+msgid "Internal server error, try later"
+msgstr "Внутренняя ошибка сервера. Попробуйте зайти позже"
+
+msgid "Your form has been sent."
+msgstr "Ваша форма была отправлена."
+
+msgid "Application"
+msgstr "Приложение"
+
+msgid "XMPP links"
+msgstr "XMPP ссылки"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Открывать XMPP ссылки в Jappix"
+
+msgid "changed the subject to:"
+msgstr "изменил тему на:"
+
+msgid "Welcome!"
+msgstr "Добро пожаловать!"
+
+msgid "Friends"
+msgstr "Друзья"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Добро пожаловать в Jappix, Вашу социальную сеть!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "До начала использования вам надо изменить некоторые установки, найти друзей и заполнить профиль."
+
+msgid "Enable notification sounds"
+msgstr "Включить звуковые уведомления"
+
+msgid "Share your position on the globe"
+msgstr "Поделится своим мемтоположением"
+
+msgid "Offline friends"
+msgstr "Друзья оффлайн"
+
+msgid "Don't hide offline friends"
+msgstr "Не скрывать друзей оффлайн"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Используйте это для поиска друзей, или добавьте их позже"
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Прекрасная работа! Итак, можете поделиться Jappix с друзьями!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr "Нажатие на кнопку сохранения открывает редактор профиля. Удачного общения!"
+
+msgid "Share Jappix on %s"
+msgstr "Рассказать про Jappix в %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Использую для общения Jabber-сеть Jappix. Я - %s!"
+
+msgid "Unknown name"
+msgstr "Неизвестное имя"
+
+msgid "Unknown country"
+msgstr "Неизвестная страна"
+
+msgid "Click to enable"
+msgstr "Включить"
+
+msgid "Click to disable"
+msgstr "Выключить"
+
+msgid "Installation"
+msgstr "Установка"
+
+msgid "Jappix installation"
+msgstr "Установка Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Добро пожаловать в установку Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Этот мастер поможет вам быстро установить Jappix, первую полноценную социальную платформу на XMPP-протоколе. Для установки не требуется особых технических навыков."
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr "Добро пожаловать"
+
+msgid "Storage configuration"
+msgstr "Настройка хранилища"
+
+msgid "Administrator account"
+msgstr "Администраторсикий акаунт"
+
+msgid "Main configuration"
+msgstr "Основные настройки"
+
+msgid "Hosts configuration"
+msgstr "Конфигурация хостов"
+
+msgid "Services installation"
+msgstr "Установка сервиса"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Если текущий язык не совпадает с вашим (%1s), вы можете настроить Jabbix на %2s."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Если хотите получить какую-либо помощь по установке и настройке Jappix, можете использовать полную документацию, доступную на:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Пришло время создать свое социальное облако: переходите к следующему шагу!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix сохраняет постоянные данные (такие, как общие файлы, логи переписки, вашу музыку и собственные настройки) в единой защищенной папке."
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix должен иметь возможность записывать в эту папку, чтобы создавать в ней под-директории. Вы должны установить права на %1s или сменить владельца папки на %2s (в зависимости от конфигурации)."
+
+msgid "The folder is writable, you can continue!"
+msgstr "Папка доступна для записи, можно продолжать!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jabbix позволяет вам управлять конфигурацией, устанавливать новые плагины или проверять обновления. Для доступа к панели управления требуется создать учетную запись администратора."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Опа! Вы вы что-то забыли, или два пароля не совпали!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix требуются некоторые значения для работы. Пожалуйста исправьте следующие строки (или оставьте по умолчанию, они подходят большинству пользователей)"
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Примечание: если вы не заполните необходимое значение, оно будет автоматически заполнено значением по умолчанию."
+
+msgid "User"
+msgstr "Пользователь"
+
+msgid "Service"
+msgstr "Сервис"
+
+msgid "Service name"
+msgstr "Имя сервиса"
+
+msgid "Service description"
+msgstr "Описание сервиса"
+
+msgid "Connection"
+msgstr "Сединение"
+
+msgid "Lock the host"
+msgstr "Заблокировать хост"
+
+msgid "Anonymous mode"
+msgstr "Анонимны режим"
+
+msgid "Registration allowed"
+msgstr "Регистрация дозволена"
+
+msgid "Use a proxy"
+msgstr "Использовать proxy"
+
+msgid "Encryption"
+msgstr "Шифрование"
+
+msgid "HTTPS storage"
+msgstr "HTTPS хранилище"
+
+msgid "Force HTTPS"
+msgstr "Принудительно использовать HTTPS"
+
+msgid "Compression"
+msgstr "Сжатие"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "На этой странице можно задать сервер, с которым Jappix будет соединяться по умолчанию. Вы можете оставить его как есть, если хотите использовать официальные серверы."
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "Возможно вы не знаете, что такое BOSH сервер? Фактически это переходник между Jappix-клиентом и XMPP-сервером, необходимый в силу технических ограничений."
+
+msgid "Main host"
+msgstr "Основной хост"
+
+msgid "Groupchat host"
+msgstr "Хост конференций"
+
+msgid "Anonymous host"
+msgstr "Анонимный хост"
+
+msgid "Directory host"
+msgstr "Хост директорий"
+
+msgid "BOSH host"
+msgstr "BOSH хост"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Вы можете установить дополнительное ПО на вашем сервере для расширения функционала. Некоторые могут быть изменены, из-за ограничений безопасности устанавливаемых по умолчанию. "
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Для этого вам необходимо иметь root-доступ к консоли вашего сервера. Помните - это необязательные модули, Jappix будет работать и без них, но некоторые возможности будут недоступны."
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "После окончания установки, Jappix сгенерирует файлы кеша. Процесс может занять некоторое время, не нажимайте на кнопки и подождите, пока не отобразится окно приложения."
+
+msgid "Thanks for using Jappix!"
+msgstr "Спасибо за использование Jappix"
+
+msgid "Next"
+msgstr "Следующий"
+
+msgid "Finish"
+msgstr "Готово"
+
+msgid "Check again"
+msgstr "Проверьте снова"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Папка защищена от записи, установите права на запись для директории %s."
+
+msgid "%s is installed on your system."
+msgstr "%s установлен на вашей системе."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s не установлен в вашей системе, вам необходимо установить %2s. "
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "Максимальный загружаемый файл в PHP %s."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "Текущего PHP maximum upload size недостаточно (%1s). Вы должны определить допустимый размер на %2s в %3s."
+
+msgid "Jappix manager"
+msgstr "Менеджер Jappix"
+
+msgid "Manager access"
+msgstr "Менеджер доступа"
+
+msgid "Statistics"
+msgstr "Статистика"
+
+msgid "Hosts"
+msgstr "Хосты"
+
+msgid "Design"
+msgstr "Дизайн"
+
+msgid "Repeat"
+msgstr "Повтор"
+
+msgid "All"
+msgstr "Все"
+
+msgid "Horizontal"
+msgstr "Горизонтальный"
+
+msgid "Vertical"
+msgstr "Вертикальный"
+
+msgid "Center"
+msgstr "Середина"
+
+msgid "Left"
+msgstr "Левый"
+
+msgid "Right"
+msgstr "Правый"
+
+msgid "Top"
+msgstr "Верх"
+
+msgid "Bottom"
+msgstr "Низ"
+
+msgid "Adapt"
+msgstr "Принять"
+
+msgid "Color"
+msgstr "Цвет"
+
+msgid "Users"
+msgstr "Пользователи"
+
+msgid "Updates"
+msgstr "Обновления"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Запретная область: лишь утвержденные пользователи могут править этот узел Jappix."
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Используйте нижеприведенную форму для доступа к панели администрирования."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "В целях безопасности сессия ограничена по времени, и, когда ваш браузер будет закрыт, вы также выйдете из нее."
+
+msgid "Credentials"
+msgstr "Полномочия"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Вы вышли из системы. До свидания!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Опа! Вы не признаны действующим администратором. Проверьте ваши полномочия!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Основные статистические данные о важных событиях, обработанные Jappix, вы можете найти ниже."
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Измените конфигурацию узла Jappix, этим инструментом."
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Измените XMPP хосты, обслуживаемые этим Jappix узлом, этим инструментом."
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Всеми хранящимися на этом Jappix узлое файлами, можно управлять с помощью этого инструмента: Пожалуйста, выберите под-директорию и начните редактировать ее содержимое!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix полностью настраиваемый: вы можете изменить его дизайн прямо здесь."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Это недопустимый формат изображения, пожалуйста используйте PNG, GIF или JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Изображение не может быть получено. Не хотите попробовать снова?"
+
+msgid "Your image was added to the list!"
+msgstr "Ваш рисунок был добавлен к списку!"
+
+msgid "Changes saved!"
+msgstr "Изменения сохранены!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Вы можете определить более одного администратора для этого Jappix узла. Также можно сменить пароль, с помощью этого инструмента."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Обновите Jappix узел этим инструментом, или проверьте, не доступен ли новый. Информация о последней версии тоже отображается (на английском)"
+
+msgid "Access statistics"
+msgstr "Доступ к статистике"
+
+msgid "Share statistics"
+msgstr "Поделится статистикой"
+
+msgid "Other statistics"
+msgstr "Другая статистика"
+
+msgid "January"
+msgstr "Январь"
+
+msgid "February"
+msgstr "Февраль"
+
+msgid "March"
+msgstr "Март"
+
+msgid "April"
+msgstr "Апрель"
+
+msgid "May"
+msgstr "Май"
+
+msgid "June"
+msgstr "Июнь"
+
+msgid "July"
+msgstr "Июль"
+
+msgid "August"
+msgstr "Август"
+
+msgid "September"
+msgstr "Сентябрь"
+
+msgid "October"
+msgstr "Октябрь"
+
+msgid "November"
+msgstr "Ноябрь"
+
+msgid "December"
+msgstr "Декабрь"
+
+msgid "Monday"
+msgstr "Понедельник"
+
+msgid "Tuesday"
+msgstr "Вторник"
+
+msgid "Wednesday"
+msgstr "Среда"
+
+msgid "Thursday"
+msgstr "Четверг"
+
+msgid "Friday"
+msgstr "Пятница"
+
+msgid "Saturday"
+msgstr "Суббота"
+
+msgid "Sunday"
+msgstr "Воскресенье"
+
+msgid "Total"
+msgstr "Всего"
+
+msgid "Cache"
+msgstr "Кеш"
+
+msgid "Logs"
+msgstr "История"
+
+msgid "Music"
+msgstr "Музыка"
+
+msgid "Backgrounds"
+msgstr "Фон"
+
+msgid "Share"
+msgstr "Поделиться"
+
+msgid "Background"
+msgstr "Фон"
+
+msgid "Notice"
+msgstr "Уведомление"
+
+msgid "Your design preferences have been saved!"
+msgstr "Ваши настройки дизайна были сохранены!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Пожалуйста проверьте ввод: чего-то не хватает!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Измените фон вашего Jappix узла этим инструментом. Вы можете установить свой цвет или загрузить изображение. Дайте волю фантазии!"
+
+msgid "Use default background"
+msgstr "Использовать фон по умолчанию."
+
+msgid "Use your own image"
+msgstr "Использовать собственную картинку"
+
+msgid "Select a background to use and change the display options."
+msgstr "Выберите фон и смените параметры оторажения."
+
+msgid "Use your own color"
+msgstr "Использовать собственний цвет"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Введите шеснадцатиричное значение цвета, который вы хотите использовать для фона."
+
+msgid "Manage backgrounds"
+msgstr "Управление фоном"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Вы можете добавить новый фон в список, этим инструментом. Пожалуйста, добавьте поддерживаемое изображение."
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Если вы хотите удалить фоновые картинки, используйте браузер ниже."
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Вы можете установить предупреждения и уведомления на главной странице с помощью этого инструмента."
+
+msgid "Simple notice"
+msgstr "Простое уведомление"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Это уведомление должно быть обычным текстом, код не допустим!"
+
+msgid "Advanced notice"
+msgstr "Расширенное уведомление"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Вы можете настроить вид уведомления с помощью HTML, CSS и JavaScript, но вам нужно написать стиль."
+
+msgid "Available updates"
+msgstr "Доступные обновления"
+
+msgid "What's new?"
+msgstr "Что нового?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Ваши папки хранения защищены от записи. Пожалуйста, установите соответствующие права!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s может вызвать проблемы с proxy, пожалуйста увеличте значение %2s до %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Вы используете версию разработчика для Jappix. Обновите ее из нашего репозитория выполнив: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Доступна новая версия Jappix! Проверьте изменения и запустите обновление!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Ваша версия устарела. Обновите ее до %s, кликнув здесь!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Вашу версию неплохо бы обновить, но вы можете выбрать обновление собственноручно кликнув здесь."
+
+msgid "Check for updates"
+msgstr "Проверить обновления"
+
+msgid "Update in progress"
+msgstr "Обновление..."
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix был обновлен: теперь у вас запущена свежайшая версия. Наслаждайтесь!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Ошибка при обновлении! Попробуйте еще раз."
+
+msgid "Downloading package..."
+msgstr "Загрузка пакета..."
+
+msgid "Removing current Jappix system files..."
+msgstr "Удаление текущих системных файлов Jappix..."
+
+msgid "Extracting package..."
+msgstr "Извлечение пакета..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Восстановление дерева каталога..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix обновлен!"
+
+msgid "Aborted: socket error!"
+msgstr "Прервано: ошибка сокета!"
+
+msgid "Aborted: buffer error!"
+msgstr "Прервано: ошибка буфера!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Прервано: все защищено от записи!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Прервано: невозможно извлечь пакет!"
+
+msgid "Visits"
+msgstr "Посещения"
+
+msgid "Daily"
+msgstr "Ежедневно"
+
+msgid "Weekly"
+msgstr "Еженедельно"
+
+msgid "Monthly"
+msgstr "Ежемесячно"
+
+msgid "Yearly"
+msgstr "Ежегодно"
+
+msgid "Size"
+msgstr "Размер"
+
+msgid "Clean everything"
+msgstr "Очистить все"
+
+msgid "Purge cache"
+msgstr "Очистить кеш"
+
+msgid "Purge logs"
+msgstr "Очистить историю"
+
+msgid "Purge updates"
+msgstr "Удалить обновления"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Папка которую вы хотите очистить, пуста."
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Храните свой Jappix узел в чистоте и порядке, регулярно очищайте папки хранения!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Выгрузите вашу музыку (Ogg Vorbis, MP3 или WAV), чтобы слушать ее в Jappix!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Файл который вы хотите загрузить должен быть меньше %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Будьте в курсе того, что хранят ваши пользователи на вашем сервере, и удаляйте нежелательный контент этим инструментом."
+
+msgid "Title"
+msgstr "Название"
+
+msgid "Artist"
+msgstr "Артист"
+
+msgid "Album"
+msgstr "Альбом"
+
+msgid "File"
+msgstr "Файл"
+
+msgid "Upload"
+msgstr "Загрузить"
+
+msgid "The folder is empty."
+msgstr "Эта папка пуста."
+
+msgid "The music could not be received, please retry!"
+msgstr "Не удалось получить музыку, пожалуйста попробуйте снова!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Это недопустимый аудио файл, пожалуйста, используйте Ogg Vorbis, MP3 или WAV!"
+
+msgid "Your music has been added!"
+msgstr "Ваша музыка добавлена!"
+
+msgid "The selected elements have been removed."
+msgstr "Выбранный элемент бил удален."
+
+msgid "You must select elements to remove!"
+msgstr "Выберите удаляемые элементы!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Добавить нового пользователя или изменить пароль (ввести существующее имя). Используйте сложный пароль!"
+
+msgid "Manage"
+msgstr "Управление"
+
+msgid "List"
+msgstr "Список"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Вы можете удалять пользователей с помощью этого инструмента. Имейте в виду, что нельзя удалить последнего оставшегося пользователя."
+
+msgid "The user has been added!"
+msgstr "Пользователь добавлен!"
+
+msgid "The chosen users have been removed."
+msgstr "Выбранные польззователи удалены."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Выберите одного или более для удаления!"
+
+msgid "Yesterday"
+msgstr "Вчера"
+
+msgid "%s days ago"
+msgstr "%s дней назад"
+
+msgid "User currently active"
+msgstr "Сейчас активен"
+
+msgid "Last seen: %s"
+msgstr "Последний раз был: %s"
+
+msgid "Inactive since: %s"
+msgstr "Бездействует с %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Похоже ваши друзья не получают сообщений!"
+
+msgid "Static content server"
+msgstr "Сервер статического контента"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Это сервер статического контента для %1, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Рекомендованые друзья"
+
+msgid "Check all"
+msgstr "Отметить все"
+
+msgid "Uncheck all"
+msgstr "Отменить выбор"
+
+msgid "Choose"
+msgstr "Выберите"
+
+msgid "List name"
+msgstr "Фамилия"
+
+msgid "Allow"
+msgstr "Зазрешить"
+
+msgid "Deny"
+msgstr "Отказать"
+
+msgid "Group"
+msgstr "Группа"
+
+msgid "Subscription"
+msgstr "Подписка"
+
+msgid "Both"
+msgstr "Оба"
+
+msgid "From"
+msgstr "От"
+
+msgid "Everybody"
+msgstr "Все"
+
+msgid "Send messages"
+msgstr "Послать сообщение"
+
+msgid "Send queries"
+msgstr "Послать запрос"
+
+msgid "See my status"
+msgstr "Смотри мой статус"
+
+msgid "Send his/her status"
+msgstr "Отправлять статус"
+
+msgid "Everything"
+msgstr "Все"
+
+msgid "Item"
+msgstr "Предмет"
+
+msgid "Order"
+msgstr "Запрос"
+
+msgid "Active for this session"
+msgstr "Активный на сессию"
+
+msgid "Always active"
+msgstr "Всегда активный"
+
+msgid "User directory"
+msgstr "Каталог пользователя"
+
+msgid "Search a friend"
+msgstr "Поиск друга"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr "Запрошенная функция не выполнена получателем или сервером, поэтому не может быть обработана."
+
+msgid "This is a repeat from %s"
+msgstr "Это повтор от %s"
+
+msgid "Loading comments..."
+msgstr "Загрузка комментариев..."
+
+msgid "Type your comment here..."
+msgstr "Введите свой комментарий..."
+
+msgid "Could not get the comments!"
+msgstr "Не удалось получить комментарии!"
+
+msgid "Show comments"
+msgstr "Показать комментарии"
+
+msgid "Send him/her a message"
+msgstr "Отправить сообщение"
+
+msgid "Start a chat with him/her"
+msgstr "Начать беседу"
+
+msgid "Media integration"
+msgstr "Медиа-интеграция"
+
+msgid "Comments locked!"
+msgstr "Комментарии заблокированы!"
+
+msgid "Type something you want to share with your friends..."
+msgstr "Напишите то, чем вы хотите поделиться с друзьями..."
+
+msgid "changed his/her nickname to %s"
+msgstr "сменил ник на %s"
+
+msgid "commented an item you follow: “%s”."
+msgstr "прокомментировал сообщение за которым вы следите: “%s”."
+
+msgid "Hide"
+msgstr "Скрыть"
+
+msgid "liked your post: “%s”."
+msgstr "понравилось ваше сообщение: “%s”."
+
+msgid "quoted you somewhere: “%s”."
+msgstr "цитировал вас где-то: “%s”."
+
+msgid "published on your wall: “%s”."
+msgstr "опубликовал на вашей стене: “%s”."
+
+msgid "tagged you in a photo (%s)."
+msgstr "отметил вас на фото (%s)."
+
+msgid "tagged you in a video (%s)."
+msgstr "отметил вас на видео (%s)."
+
+msgid "Show"
+msgstr "Показать"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr "Нужна помощь? Вам лучше прочитать страницу документации, о том, как заполнять эту форму!"
+
+msgid "Pubsub host"
+msgstr "Хост Pubsub"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr "Jappix это великолепная социальная платформа, в которой ты можешь общаться с кем и когда угодно."
+
+msgid "Manager link"
+msgstr "Менеджер ссылок"
+
+msgid "User uploads server"
+msgstr "Сервер загрузок пользователя"
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr "Это сервер пользовательских загрузок для %1s, “%2s”."
+
+msgid "Logo"
+msgstr "Логотип"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr "Вы можете установить собственный логотип. Уделите внимание размеру и цвету каждого логотипа!"
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr "Выгрузите каждый логотип с рекомендованным максимальным размером в пикселях."
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Неподдерживаемый графический формат, пожалуйста используйте формат PNG!"
+
+msgid "Your service logo has been successfully changed!"
+msgstr "Ваш логотип был успешно заменен!"
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Формат логотипа должен быть PNG. Оставьте поле пустым, чтобы не изменять."
+
+msgid "Remove this logo"
+msgstr "Удалить логотип"
+
+msgid "View this logo"
+msgstr "Посмотреть логотип"
+
+msgid "Send a file"
+msgstr "Отправить файл"
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr "После выгрузки, ваш друг получит запрос на загрузку отправленного вами файла,"
+
+msgid "Groupchats to join"
+msgstr "Конференции для вступления"
+
+msgid "Purge sent files"
+msgstr "Удалить отправленные файлы"
+
+msgid "would like to send you a file: “%s”."
+msgstr "хочет выслать вам файл: “%s”."
+
+msgid "has accepted to received your file: “%s”."
+msgstr "согласился на получение вашего файла: “%s”."
+
+msgid "has rejected to receive your file: “%s”."
+msgstr "отколнил получение вашего файла: “%s”."
+
+msgid "could not receive your file: “%s”."
+msgstr "не может получить ваш файл: “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr "получил запрос на обмен файлами: “%s”."
+
+msgid "Available shortcuts:"
+msgstr "Доступные ярлыки:"
+
+msgid "%s removes the chat logs"
+msgstr "%s удаляет логи чатов"
+
+msgid "%s joins a groupchat"
+msgstr "%s присоединяет к конференции"
+
+msgid "%s closes the chat"
+msgstr "%s закрывает чат"
+
+msgid "%s shows the user profile"
+msgstr "%s отображает профиль пользователя"
+
+msgid "%s sends a message to the room"
+msgstr "%s отправляет сообщение в комнату"
+
+msgid "%s changes your nickname"
+msgstr "%s изменяет ваш ник"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s отправляет сообщение кому-то из комнаты"
+
+msgid "%s changes the room topic"
+msgstr "%s изменяет тему комнаты"
+
+msgid "%s kicks an user of the room"
+msgstr "%s выставляет пользователя из комнаты"
+
+msgid "%s bans an user of the room"
+msgstr "%s блокирует пользователя в комнате"
+
+msgid "%s invites someone to join the room"
+msgstr "%s приглашает кого-то войти в комнату"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix это некоммерческая общественная платформа, доступная откуда бы ни было, когда бы ни пожелаете и с кем бы ни решили пообщаться."
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/sk/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/sk/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..4e12dbf
Binary files /dev/null and b/jappixmini/jappix/lang/sk/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/sk/LC_MESSAGES/main.po b/jappixmini/jappix/lang/sk/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..d9c24be
--- /dev/null
@@ -0,0 +1,1870 @@
+# Slovak translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Vo vašom prehliadači chýba JavaScript, takže nebude možné spustiť Jappix! Prosím napravte to."
+
+msgid "An open social network"
+msgstr "Otvorená sociálna sieť"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix bol prerušený problémom so sieťou, chybou alebo nesprávnym prihlásením (skontrolujte či sú zadané údaje správne). Ospravedlňujeme sa za nepríjemnosti."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Zoznam komponentov na tomto serveri nie je možné získať!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Vaše heslo bolo zmenené, teraz sa môžete prihlásiť k vášmu účtu s novými prihlasovacími údajmi."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Váš XMPP účet bol zmazaný, dovidenia!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Boli ste odhlásený z vášho XMPP účtu, prajem pekný deň!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Zdá sa, že miestnosť do ktorej ste vstúpili neexistuje, Vytvárate ju!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Skupinový rozhovor bol odstránený, teraz ho bude môcť vytvoriť niekto iný."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Užívateľ, ktorého chcete zastihnúť sa v tejto miestnosti nenachádza"
+
+msgid "Please enter the group chat address to join."
+msgstr "Prosím, vyplňte adresu skupinového rozhovoru ku ktorému sa chcete pripojiť"
+
+msgid "Please enter your nickname to join %s."
+msgstr "Prosím, vyplňte prezývku pre pripojenie do %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Táto miestnosť (%s) je chránená heslom."
+
+msgid "Your browser is out of date!"
+msgstr "Váš prehliadač je zastaralý"
+
+msgid "Last %s version is better!"
+msgstr "Posledná %s verzia je lepšia!"
+
+msgid "Login"
+msgstr "Prihlásenie"
+
+msgid "Register"
+msgstr "Registrácia"
+
+msgid "Here we go!"
+msgstr "Poďme na to!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Heslo"
+
+msgid "Remember me"
+msgstr "Zapamätaj si ma"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Táto možnosť bola zakázaná, nemôžete ju použiť!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Pre problémy so sieťou ste boli odhlásený, Čo chcete robiť?"
+
+msgid "Reconnect"
+msgstr "Znovu pripojiť"
+
+msgid "Messages"
+msgstr "Správy"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Možnosti"
+
+msgid "Disconnect"
+msgstr "Odpojiť"
+
+msgid "Filter"
+msgstr "Filter"
+
+msgid "Add a friend"
+msgstr "Pridať priateľa"
+
+msgid "Your groupchats"
+msgstr "Vaše skupinové rozhovory"
+
+msgid "Manage your favorite groupchats"
+msgstr "Spravovať vaše obľúbené skupinové rozhovory"
+
+msgid "More stuff"
+msgstr "Ďalšie možnosti"
+
+msgid "Show all friends"
+msgstr "Zobraziť všetkých priateľov"
+
+msgid "Only show connected friends"
+msgstr "Zobraziť iba pripojených priateľov"
+
+msgid "Message archives"
+msgstr "Archív správ"
+
+msgid "Date"
+msgstr "Dátum"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Vyberte priateľa pre zobrazenie histórie rozhovoru."
+
+msgid "Nothing found for: %s"
+msgstr "Žiaden výsledok pre: %s"
+
+msgid "A short message?"
+msgstr "Krátka správa?"
+
+msgid "How are you?"
+msgstr "Ako sa máš?"
+
+msgid "What are you doing?"
+msgstr "Čo robíš?"
+
+msgid "Join a chat"
+msgstr "Začať rozhovor"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "Available"
+msgstr "Prihlásený"
+
+msgid "Talkative"
+msgstr "Zhovorčivý"
+
+msgid "Away"
+msgstr "Neprítomný"
+
+msgid "Not available"
+msgstr "Neprihlásený"
+
+msgid "Busy"
+msgstr "Zaneprázdnený"
+
+msgid "Mood"
+msgstr "Nálada"
+
+msgid "None"
+msgstr "Nič"
+
+msgid "Crazy"
+msgstr "Bláznivá"
+
+msgid "Excited"
+msgstr "Vzrušenie"
+
+msgid "Playful"
+msgstr "Hravá"
+
+msgid "Happy"
+msgstr "Šťastný"
+
+msgid "Shocked"
+msgstr "Šokovaný"
+
+msgid "Hot"
+msgstr "Nažhavený"
+
+msgid "Sad"
+msgstr "Smutný"
+
+msgid "Amorous"
+msgstr "Zamilovaný"
+
+msgid "Confident"
+msgstr "Dôverčivý"
+
+msgid "Activity"
+msgstr "Aktivita"
+
+msgid "Chores"
+msgstr "Fuška"
+
+msgid "Drinking"
+msgstr "Pije"
+
+msgid "Eating"
+msgstr "Jedenie"
+
+msgid "Exercising"
+msgstr "Vzdelávanie"
+
+msgid "Grooming"
+msgstr "Starostlivosť"
+
+msgid "Appointment"
+msgstr "Stretnutie"
+
+msgid "Inactive"
+msgstr "Neaktívny"
+
+msgid "Relaxing"
+msgstr "Relax"
+
+msgid "Talking"
+msgstr "Rozhovor"
+
+msgid "Traveling"
+msgstr "Cestovanie"
+
+msgid "Working"
+msgstr "Práca"
+
+msgid "View profile"
+msgstr "Zobraziť profil"
+
+msgid "Repeat this notice"
+msgstr "Zopakovať toto upozornenie"
+
+msgid "Remove this notice"
+msgstr "Odstrániť toto upozornenie"
+
+msgid "Your profile"
+msgstr "Váš profil"
+
+msgid "Identity"
+msgstr "Identita"
+
+msgid "Profile image"
+msgstr "Profilová fotka"
+
+msgid "Others"
+msgstr "Iné"
+
+msgid "Personal"
+msgstr "Osobné"
+
+msgid "Complete name"
+msgstr "Celé meno"
+
+msgid "Nickname"
+msgstr "Prezývka"
+
+msgid "First name"
+msgstr "Meno"
+
+msgid "Last name"
+msgstr "Priezvisko"
+
+msgid "Date of birth"
+msgstr "Dátum narodenia"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-mail"
+
+msgid "Phone"
+msgstr "Telefón"
+
+msgid "Website"
+msgstr "Webstránka"
+
+msgid "Current"
+msgstr "Momentálne"
+
+msgid "Delete"
+msgstr "Zmazať"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Aká škoda! Nemáte nastavenú profilovú fotku vo vašej vizitke!"
+
+msgid "Address"
+msgstr "Adresa"
+
+msgid "Street"
+msgstr "Ulica"
+
+msgid "City"
+msgstr "Mesto"
+
+msgid "Postal code"
+msgstr "PSČ"
+
+msgid "Country"
+msgstr "Krajina"
+
+msgid "Biography"
+msgstr "Biografia"
+
+msgid "Important notice"
+msgstr "Dôležitý oznam"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Buďte opatrní, informácie ktoré vyplníte v profile sú prístupné každému (aj niekomu, koho si neželáte)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Nie všetko je súkromné v XMPP; toto je jedna z týchto vecí, váš verejný profil (vCard)"
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Odporúčame nahrať profilovku (%s maximum), napríklad vašu fotku, aby vás priatelia ľahšie rozpoznali."
+
+msgid "Save"
+msgstr "Uložiť"
+
+msgid "Cancel"
+msgstr "Zrušiť"
+
+msgid "Edit options"
+msgstr "Upraviť možnosti"
+
+msgid "Channel"
+msgstr "Kanál"
+
+msgid "Commands"
+msgstr "Príkazy"
+
+msgid "Sounds"
+msgstr "Zvuky"
+
+msgid "Privacy"
+msgstr "Súkromie"
+
+msgid "Message archiving"
+msgstr "Archivácia správ"
+
+msgid "Store a history of your chats"
+msgstr "Ukladať históriu vašich rozhovorov"
+
+msgid "Geolocation"
+msgstr "Geolokácia"
+
+msgid "Empty"
+msgstr "Vymazanie"
+
+msgid "Empty channel"
+msgstr "Vymazať kanál"
+
+msgid "Persistent"
+msgstr "Natrvalo"
+
+msgid "Maximum notices"
+msgstr "Maximum upozornení"
+
+msgid "Account"
+msgstr "Účet"
+
+msgid "Change password"
+msgstr "Zmeniť heslo"
+
+msgid "Delete account"
+msgstr "Zmazať účet"
+
+msgid "Old"
+msgstr "Staré"
+
+msgid "New (2 times)"
+msgstr "Nové (2 krát)"
+
+msgid "Continue"
+msgstr "Pokračuj"
+
+msgid "To"
+msgstr "Komu"
+
+msgid "Close"
+msgstr "Zavrieť"
+
+msgid "unknown"
+msgstr "neznáme"
+
+msgid "Unavailable"
+msgstr "Nie je k dispozícii"
+
+msgid "is now"
+msgstr "je teraz"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Prosím počkajte pokiaľ sa nahrá váš avatar.."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Tu je! Nová krásna profilová fotka!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Súbor s obrázkom nie je podporovaný alebo má nesprávnu veľkosť"
+
+msgid "Reply"
+msgstr "Odpovedať"
+
+msgid "Error"
+msgstr "Chyba"
+
+msgid "Click here to solve the error"
+msgstr "Kliknite sem pre riešenie problému"
+
+msgid "You"
+msgstr "Ty"
+
+msgid "Remove"
+msgstr "Odstrániť"
+
+msgid "Rename"
+msgstr "Premenovať"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Ahoj, Ja som %s, chcem si ťa pridať ako priateľa"
+
+msgid "Smiley insertion"
+msgstr "Smajlíci"
+
+msgid "Change style"
+msgstr "Zmeň štýl"
+
+msgid "Text in bold"
+msgstr "Tučné"
+
+msgid "Text in italic"
+msgstr "Italic"
+
+msgid "Underlined text"
+msgstr "Podčiarknuté"
+
+msgid "Save chat"
+msgstr "Uložiť rozhovor"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Klikni na nasledujúci link pre vytvorenie logu a počkaj. Potom klikni znova pre prevzatie súboru."
+
+msgid "This chat is empty!"
+msgstr "Tento rozhovor je prázdny"
+
+msgid "Generate file!"
+msgstr "Vygeneruj súbor!"
+
+msgid "Download file!"
+msgstr "Stiahni súbor!"
+
+msgid "Clean current chat"
+msgstr "Vyčisti prebiehajúci rozhovor"
+
+msgid "View chat history"
+msgstr "Ukáž históriu rozhovoru"
+
+msgid "Show user profile"
+msgstr "Ukáž používateľov profil"
+
+msgid "Add this contact to your friends"
+msgstr "Pridaj tento kontakt medzi priateľov"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Pridať tento skupinový rozhovor k obľúbeným"
+
+msgid "All tabs"
+msgstr "Všetky karty"
+
+msgid "Close this tab"
+msgstr "Zavrieť túto kartu"
+
+msgid "no subject defined for this room."
+msgstr "Nebol nastavený predmet pre túto miestnosť"
+
+msgid "Administration panel for this room"
+msgstr "Panel administrácie pre túto miestnosť"
+
+msgid "Moderators"
+msgstr "Moderátori"
+
+msgid "Participants"
+msgstr "Členovia"
+
+msgid "Visitors"
+msgstr "Návštevníci"
+
+msgid "Manage favorite rooms"
+msgstr "Spravovať obľúbené skupinové rozhovory"
+
+msgid "Change favorites"
+msgstr "Zmeniť obľúbené"
+
+msgid "Search a room"
+msgstr "Prehľadať miestnosť"
+
+msgid "Select a favorite"
+msgstr "Vyber obľúbené"
+
+msgid "Getting the name..."
+msgstr "Získavam meno..."
+
+msgid "Gateway"
+msgstr "Brána"
+
+msgid "Name"
+msgstr "Meno"
+
+msgid "Room"
+msgstr "Miestnosť"
+
+msgid "Add"
+msgstr "Pridať"
+
+msgid "Edit"
+msgstr "Upraviť"
+
+msgid "Search a room on"
+msgstr "Hľadať miestnosť na"
+
+msgid "No room found on this server."
+msgstr "Žiadna miestnosť sa nenašla na tomto serveri"
+
+msgid "Service discovery"
+msgstr "Vyhľadávanie služieb"
+
+msgid "Server to query"
+msgstr "Server na prehľadanie"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Ospravedňujeme sa, ale výraz nevrátil žiaden výsledok"
+
+msgid "Accounts"
+msgstr "Účty"
+
+msgid "Authentications"
+msgstr "Autentifikácia"
+
+msgid "Automation"
+msgstr "Automatizácia"
+
+msgid "Clients"
+msgstr "Klienti"
+
+msgid "Collaboration"
+msgstr "Spolupráca"
+
+msgid "Components"
+msgstr "Komponenty"
+
+msgid "Rooms"
+msgstr "Miestnosti"
+
+msgid "Directories"
+msgstr "Adresáre"
+
+msgid "Gateways"
+msgstr "Brány"
+
+msgid "News"
+msgstr "Novinky"
+
+msgid "Hierarchy"
+msgstr "Hierarchia"
+
+msgid "Proxies"
+msgstr "Proxy servery"
+
+msgid "Publication/Subscription"
+msgstr "Publikovanie/Odoberanie"
+
+msgid "Storage"
+msgstr "Úložisko"
+
+msgid "Service offline or broken"
+msgstr "Služba je vypnutá alebo nefunkčná"
+
+msgid "Your inbox"
+msgstr "Vaše prijaté správy"
+
+msgid "Available actions"
+msgstr "Dostupné akcie"
+
+msgid "Clean"
+msgstr "Vyčistiť"
+
+msgid "New"
+msgstr "Nová"
+
+msgid "Received"
+msgstr "Prijaté"
+
+msgid "Subject"
+msgstr "Predmet"
+
+msgid "Content"
+msgstr "Obsah"
+
+msgid "Send message"
+msgstr "Poslať správu"
+
+msgid "Your inbox is empty."
+msgstr "Vaša schránka prijatých správ je prázdna"
+
+msgid "MUC administration"
+msgstr "MUC administrácia"
+
+msgid "You administrate this room"
+msgstr "Spravujete túto miestnosť"
+
+msgid "Enter new subject"
+msgstr "Vložte nový predmet"
+
+msgid "Configuration"
+msgstr "Konfigurácia"
+
+msgid "Authorizations"
+msgstr "Autorizácia"
+
+msgid "Member list"
+msgstr "Zoznam členov"
+
+msgid "Owner list"
+msgstr "Zoznam vlastníkov"
+
+msgid "Administrator list"
+msgstr "Zoznam administrátorov"
+
+msgid "Outcast list"
+msgstr "Zoznam neželaných"
+
+msgid "Add an input"
+msgstr "Pridaj člena"
+
+msgid "Destroy this MUC"
+msgstr "Znič toto MUC"
+
+msgid "Yes, let's do it!"
+msgstr "Áno, do toho!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Váš priateľ sleduje konverzáciu"
+
+msgid "Your friend is writing a message..."
+msgstr "Váš priateľ píše..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Váš priateľ prestal písať."
+
+msgid "Your friend is doing something else."
+msgstr "Váš priateľ robí niečo iné."
+
+msgid "Your friend closed the chat."
+msgstr "Váš priateľ zavrel rozhovor"
+
+msgid "Requesting this service..."
+msgstr "Požaduje túto službu.."
+
+msgid "Loading"
+msgstr "Načítava"
+
+msgid "joined the chat room"
+msgstr "vstúpil do miestnosti"
+
+msgid "left the chat room"
+msgstr "opustil miestnosť"
+
+msgid "no status"
+msgstr "bez statusu"
+
+msgid "has been kicked"
+msgstr "bol vykopnutý"
+
+msgid "has been banned"
+msgstr "bol zabanovaný"
+
+msgid "no reason"
+msgstr "neudaný dôvod"
+
+msgid "Communicate with the entire world!"
+msgstr "Komunikujte s celým svetom!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "Umožní vám byť v kontakte s miliónmi užívateľov, ktorí práve využívajú XMPP sieť ako vy s Jappix. Pridajte sa ku komunite a zostaňte voľný!"
+
+msgid "Hi there!"
+msgstr "Ahoj!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Vitajte na %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "Prihlás sa do svojho existujúceho XMPP účtu alebo vytvor nový zadarmo!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix je open-source projekt od PostPro, neziskovej organizácie ktorá nám poskytuje veľkú podporu."
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "Prihlás sa do svojho existujúceho XMPP účtu. Taktiež možeš použiť %s pre pripojenie ku skupinovému rozhovoru"
+
+msgid "Previous"
+msgstr "Predchádzajúce"
+
+msgid "General"
+msgstr "Všeobecné"
+
+msgid "Advanced"
+msgstr "Pokročilé"
+
+msgid "Resource"
+msgstr "Zdroj"
+
+msgid "Priority"
+msgstr "Priorita"
+
+msgid "Low"
+msgstr "Nízka"
+
+msgid "Medium"
+msgstr "Stredná"
+
+msgid "High"
+msgstr "Vysoká"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "Zadajte názov skupinového rozhovoru ku ktorému sa chcete pridať a prezývku akú chcete. Alebo sa môžete vrátiť na %s."
+
+msgid "login page"
+msgstr "prihlásenie"
+
+msgid "Share this link with your friends:"
+msgstr "Zdieľaj tento odkaz s priateľmi:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "Zaregistruj nový XMPP účet a spoj sa s priateľmi vo svojej vlastnej socialnej sieti. Je to ednoduché!"
+
+msgid "Required"
+msgstr "Povinné"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Boli ste zaregistrovaný, tu je vaša XMPP adresa:"
+
+msgid "Manager"
+msgstr "Správca"
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Šifrovane"
+
+msgid "Unencrypted"
+msgstr "Nešifrované"
+
+msgid "Where are you?"
+msgstr "Kde ste?"
+
+msgid "What's up with you?"
+msgstr "Čo je s vami?"
+
+msgid "Fetching the social channel..."
+msgstr "Preberanie kanálu..."
+
+msgid "You are synchronized with your network."
+msgstr "Ste synchronizovaný s vašou sieťou"
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Nemôžete nič odoslať: môžete iba príjmať správy!"
+
+msgid "Media viewer"
+msgstr "Prehliadač médii"
+
+msgid "Browse"
+msgstr "Prehľadať"
+
+msgid "Command"
+msgstr "Príkaz"
+
+msgid "Subscribe"
+msgstr "Odoberať"
+
+msgid "Join"
+msgstr "Pridať sa"
+
+msgid "Automatic"
+msgstr "Automaticky"
+
+msgid "Search"
+msgstr "Hľadať"
+
+msgid "No result!"
+msgstr "Žiadne výsledky!"
+
+msgid "No notifications."
+msgstr "Žiadne upozornenia"
+
+msgid "would like to add you as a friend."
+msgstr "si vás chce pridať ako priateľa"
+
+msgid "would like you to join this chatroom:"
+msgstr "chce aby ste vstúpili do miestnosti:"
+
+msgid "Do you accept?"
+msgstr "Súhlasíte?"
+
+msgid "Yes"
+msgstr "Áno"
+
+msgid "No"
+msgstr "Nie"
+
+msgid "would like to get authorization."
+msgstr "žiada o povolenie."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "Chcete vidieť priateľov, ktorých vám %s navrhuje? "
+
+msgid "Submit"
+msgstr "Povoliť"
+
+msgid "Client"
+msgstr "Klient"
+
+msgid "System"
+msgstr "Systém"
+
+msgid "Local time"
+msgstr "Lokálny čas"
+
+msgid "Comments"
+msgstr "Komentáre"
+
+msgid "User profile"
+msgstr "Užívateľov profil"
+
+msgid "See his/her position on the globe"
+msgstr "Zobraz jeho/jej pozíciu na zemeguli"
+
+msgid "Confirm"
+msgstr "Potvrdiť"
+
+msgid "anonymous mode"
+msgstr "anonymný mód"
+
+msgid "Groups"
+msgstr "Skupiny"
+
+msgid "Unclassified"
+msgstr "Nezaradené"
+
+msgid "Authorize"
+msgstr "Povoliť"
+
+msgid "Ask for authorization"
+msgstr "Požiadaj o povolenie"
+
+msgid "Unblock"
+msgstr "Odblokovať"
+
+msgid "Prohibit"
+msgstr "Zakázať"
+
+msgid "Block"
+msgstr "Blokovať"
+
+msgid "Chat"
+msgstr "Rozhovor"
+
+msgid "Groupchat"
+msgstr "Skupinový rozhovor"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobile"
+
+msgid "Desktop"
+msgstr "Počítač"
+
+msgid "Mobile"
+msgstr "Mobil"
+
+msgid "Please wait..."
+msgstr "Čakajte prosím..."
+
+msgid "Please enable JavaScript"
+msgstr "Povoľte JavaScript prosím"
+
+msgid "Your channel"
+msgstr "Váš kanál"
+
+msgid "Channel of"
+msgstr "Kanál užívateľa"
+
+msgid "More notices..."
+msgstr "Ďaľšie upozornenia..."
+
+msgid "Attach a file"
+msgstr "Pripojiť súbor"
+
+msgid "Send"
+msgstr "Odoslať"
+
+msgid "Unattach the file"
+msgstr "Odpojiť súbor"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Stala sa chyba počas nahrávania vášho súboru: možno je príliš veľký ($s maximum) alebo zakázaný!"
+
+msgid "Authorization failed"
+msgstr "Overenie zlyhalo"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrácia zlyhala, zvoľte prosím iné užívateľské meno"
+
+msgid "Service unavailable"
+msgstr "Služba je nedostupná"
+
+msgid "Internal server error, try later"
+msgstr "Internal server error, skúste neskôr"
+
+msgid "Your form has been sent."
+msgstr "Váš formulár bol odoslaný"
+
+msgid "Application"
+msgstr "Aplikácia"
+
+msgid "XMPP links"
+msgstr "XMPP odkaz"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Otvoriť XMPP odkazy pomocou Jappix"
+
+msgid "changed the subject to:"
+msgstr "zmenil predmet na"
+
+msgid "Welcome!"
+msgstr "Vitajte!"
+
+msgid "Friends"
+msgstr "Priatelia"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "Vitajte na Jappix, vašej vlastnej sociálnej sieti!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "Skôr než ju začnete používať, mali by ste zmeniť niektoré nastavenia, vyhľadať priateľov a vyplniť svoj profil."
+
+msgid "Enable notification sounds"
+msgstr "Povoliť zvuk upozornení"
+
+msgid "Share your position on the globe"
+msgstr "Zdieľať svoju polohu na zemeguli"
+
+msgid "Offline friends"
+msgstr "Odpojení priatelia"
+
+msgid "Don't hide offline friends"
+msgstr "Neskrývať odpojených priateľov"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "Použite tento nástroj na vyhľadanie vašich priateľov na serveri, ktorý používate, alebo ich pridajte neskôr."
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr "Výborne! Teraz môžte zdielať Jappix s priateľmi!"
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr "Zdieľať Jappix na %s"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Používam Jappix, otvorenú socialnu platformu. Ja som %s!"
+
+msgid "Unknown name"
+msgstr "Neznáme meno"
+
+msgid "Unknown country"
+msgstr "Neznáma krajina"
+
+msgid "Click to enable"
+msgstr "Klikni pre zapnutie"
+
+msgid "Click to disable"
+msgstr "Klikni pre vypnutie"
+
+msgid "Installation"
+msgstr "Inštalácia"
+
+msgid "Jappix installation"
+msgstr "Jappix inštalácia"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Vitajte v Jappix inštalácii"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "Tento nástroj vám pomôže rýchlo nainštalovať Jappix, prvú plnohodnotnú sociálnu platformu založenú na XMPP, na váš server. Nebudete dokonca potrebovať žiadne technické znalosti.( takmer :) ))"
+
+msgid "Let's have a look at the installation steps:"
+msgstr "Poďme sa pozrieť na inštalačné kroky:"
+
+msgid "Welcome"
+msgstr "Vitajte"
+
+msgid "Storage configuration"
+msgstr "Nastavenie úložiska"
+
+msgid "Administrator account"
+msgstr "Administračný účet"
+
+msgid "Main configuration"
+msgstr "Hlavná konfigurácia"
+
+msgid "Hosts configuration"
+msgstr "Hosts configuration"
+
+msgid "Services installation"
+msgstr "Inštalácia služieb"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "Pokiaľ sa tento jazyk nezhoduje s vašim (%1s), môžete nechať Jappix hovoriť %2s.Voľba bude uložená."
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr "Pokiaľ potrebujete pomoc ohľadom inštalácie a konfigurácie Jappix, môžete použiť dokumentáciu, dostupnú na:"
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr "Nastal čas vybudovať vašu vlastnú socialnu sieť: stačí prejsť do daľšieho kroku!"
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr "Jappix ukladá natrvalo dáta (ako sú zdieľané súbory,vaša vlastná hudba a svoju konfiguráciu) do jedinej zabezpečenej zložky"
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr "Jappix musí mať právo zapisovať v tejto zložke pre vytvorenie svojich podzložiek. Ak nie, musíte nastaviť oprávnenia na %1s alebo zmeniť vlastníka zložky na %2s (závisí od vašej konfigurácie))"
+
+msgid "The folder is writable, you can continue!"
+msgstr "Do zložky je možné zapisovať, môžete pokračovať!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr "Jappix vám ponúka možnosť spravovať vaše konfiguráciu, inštalovať nové pluginy alebo vyhľadať aktualizácie. Preto si musíte vytvoriť administračný účet pre prístup k Správcovi."
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "Po nainštalovaní Jappix, stačí kliknúť na odkaz Správca na domovskej stránke pre prístup."
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Ups, niečo ste prehliadli alebo heslá nesúhlasia!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix vyžaduje nastavenie niekoľkých hodnôt. Prosím, upravte nasledujúce hodnoty (alebo ponechajte predvolené, ktoré vyhovujú väčšine užívatelov). )"
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr "Ak nenastavíte povinné údaje, budú nastavené na predvolené hodnoty"
+
+msgid "User"
+msgstr "Užívateľ"
+
+msgid "Service"
+msgstr "Služba"
+
+msgid "Service name"
+msgstr "Meno služby"
+
+msgid "Service description"
+msgstr "Popis služby"
+
+msgid "Connection"
+msgstr "Pripojenie"
+
+msgid "Lock the host"
+msgstr "Uzamknúť host"
+
+msgid "Anonymous mode"
+msgstr "Anonymný mód"
+
+msgid "Registration allowed"
+msgstr "Registrácia povolená"
+
+msgid "Use a proxy"
+msgstr "Použiť proxy"
+
+msgid "Encryption"
+msgstr "Šifrovanie"
+
+msgid "HTTPS storage"
+msgstr "HTTPS úložisko"
+
+msgid "Force HTTPS"
+msgstr "Vynútiť HTTPS"
+
+msgid "Compression"
+msgstr "Kompresia"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr "Táto stránka vám pomôže nastaviť predvoleného Hostiteľa. Použite predvolené ak chcete využívať oficialnu službu Hostiteľa"
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr "BOSH server je v podstate spojenie medzi Jappix klientom a XMPP serverom, ktoré je nevyhnutné z dôvodu technických obmedzení"
+
+msgid "Main host"
+msgstr "Hlavný hostiteľ (Main host)"
+
+msgid "Groupchat host"
+msgstr "Hostiteľ Skupinových rozhovorov (Groupchat host)"
+
+msgid "Anonymous host"
+msgstr "Anonymous host"
+
+msgid "Directory host"
+msgstr "Directory host"
+
+msgid "BOSH host"
+msgstr "BOSH host"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr "Môžete nainštalovať doplnky pre rozšírenie funkcionality Jappix. Niektoré môžete dodatočne upraviť, najmä z dôvodu bezpečnostných obmedzení, ktoré sú nastavené ako predvolené."
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr "Pre vykonanie musíte mať prístup k terminálu serveru a byť prihlásený ako root. Jappix bude pracovať aj bez týchto modulov ale niektoré z funkcii budú nedostupné"
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "Keď skončíte nastavovanie, Jappix vygeneruje cache súbory. Môže to chvíľu trvať, počkajte pokiaľ sa nezobrazí aplikácia a nestláčajte žiadne tlačidlo."
+
+msgid "Thanks for using Jappix!"
+msgstr "Ďakujeme za používanie Jappix-u!"
+
+msgid "Next"
+msgstr "Ďalej"
+
+msgid "Finish"
+msgstr "Dokončiť"
+
+msgid "Check again"
+msgstr "Opakovať"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "V zložke sa nedá zapisovať, nastavte práva pre zložku %s."
+
+msgid "%s is installed on your system."
+msgstr "%s je nainštalovaný vo vašom systéme"
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s nie je nainštalovaný vo vašom systéme, nainštalujte %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP maximum upload size je dostatočná (%s)"
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP maximum upload size nie je dostatočná (%1s), mali by ste ju nastaviť na%2s v %3s."
+
+msgid "Jappix manager"
+msgstr "Jappix správca"
+
+msgid "Manager access"
+msgstr "Administrácia"
+
+msgid "Statistics"
+msgstr "Štatistika"
+
+msgid "Hosts"
+msgstr "Hosts"
+
+msgid "Design"
+msgstr "Dizajn"
+
+msgid "Repeat"
+msgstr "Opakovať"
+
+msgid "All"
+msgstr "Všetko"
+
+msgid "Horizontal"
+msgstr "Horizontálne"
+
+msgid "Vertical"
+msgstr "Vertikálne"
+
+msgid "Center"
+msgstr "Stred"
+
+msgid "Left"
+msgstr "Vľavo"
+
+msgid "Right"
+msgstr "Vpravo"
+
+msgid "Top"
+msgstr "Hore"
+
+msgid "Bottom"
+msgstr "Dole"
+
+msgid "Adapt"
+msgstr "Prispôsobiť"
+
+msgid "Color"
+msgstr "Farba"
+
+msgid "Users"
+msgstr "Užívatelia"
+
+msgid "Updates"
+msgstr "Aktualizácie"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "Iba autorizovaní užívatelia môžu spravovať tento Jappix uzol. "
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Použite nasledujúci formulár pre prihlásenie do Administračnej sekcie."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr "Pre zvýšenie bezpečnosti je prihlásenie časovo obmedzené a po zatvorení prehliadača budete odhlásený."
+
+msgid "Credentials"
+msgstr "Overenie"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Boli ste odhlásený, Dovidenia!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Ups, neboli ste rozpoznaný ako administrátor. Skontrolujte prihlasovacie údaje!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "Štatistiky aplikácie Jappix"
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "Zmena konfigurácie uzla Jappix"
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "Zmena nastavení XMPP hostiteľov pre tento Jappix uzol"
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "Všetky súbory na tomto Jappix uzle môžete spravovať pomocou tohto nástroja: vyberte podzložku a môžete editovať jej obsah."
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix je plne prispôsobiteľný: jeho dizajn môžete zmeniť práve tu."
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Toto nie je platný obrázok, použite PNG,GIF alebo JPG "
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Obrázok nebol prijatý, prajete si zopakovať?"
+
+msgid "Your image was added to the list!"
+msgstr "Váš obrázok bol pridaný do zoznamu!"
+
+msgid "Changes saved!"
+msgstr "Zmeny uložené!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "Na tomto Jappix uzli môžte definovať viac ako jedného administrátora. Taktiež môžte zmeniť heslo."
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "Aktualizuj Jappix uzol alebo skontroluj či je dostupná nová verzia. Zobrazia sa informácie o poslednej verzii (v angličtine)"
+
+msgid "Access statistics"
+msgstr "Štatistiky prístupu"
+
+msgid "Share statistics"
+msgstr "Štatistiky zdieľania"
+
+msgid "Other statistics"
+msgstr "Ostatné štatistiky"
+
+msgid "January"
+msgstr "Január"
+
+msgid "February"
+msgstr "Február"
+
+msgid "March"
+msgstr "Marec"
+
+msgid "April"
+msgstr "Apríl"
+
+msgid "May"
+msgstr "Máj"
+
+msgid "June"
+msgstr "Jún"
+
+msgid "July"
+msgstr "Júl"
+
+msgid "August"
+msgstr "August"
+
+msgid "September"
+msgstr "September"
+
+msgid "October"
+msgstr "Október"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "December"
+
+msgid "Monday"
+msgstr "Pondelok"
+
+msgid "Tuesday"
+msgstr "Utorok"
+
+msgid "Wednesday"
+msgstr "Streda"
+
+msgid "Thursday"
+msgstr "Štvrtok"
+
+msgid "Friday"
+msgstr "Piatok"
+
+msgid "Saturday"
+msgstr "Sobota"
+
+msgid "Sunday"
+msgstr "Nedeľa"
+
+msgid "Total"
+msgstr "Celkom"
+
+msgid "Cache"
+msgstr "Cache"
+
+msgid "Logs"
+msgstr "Logy"
+
+msgid "Music"
+msgstr "Hudba"
+
+msgid "Backgrounds"
+msgstr "Pozadia"
+
+msgid "Share"
+msgstr "Zdieľanie"
+
+msgid "Background"
+msgstr "Pozadie"
+
+msgid "Notice"
+msgstr "Upozornenie"
+
+msgid "Your design preferences have been saved!"
+msgstr "Vaše nastavenie dizajnu bolo uložené"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Skontrolujte údaje, niečo chýba!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "Zmeňte pozadie vášho JAppix uzla.môžte si zvoliť farbu alebo uložený obrázok.Let your creativity flow!"
+
+msgid "Use default background"
+msgstr "Použit predvolené pozadie"
+
+msgid "Use your own image"
+msgstr "Použiť vlastný obrázok"
+
+msgid "Select a background to use and change the display options."
+msgstr "Vyberte pozadie ktoré bude použité a meňte nastavenia zobrazenia"
+
+msgid "Use your own color"
+msgstr "Použiť vlastnú farbu"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Zadajte hexadecimálnu farbu pre vaše pozadie"
+
+msgid "Manage backgrounds"
+msgstr "Spravovať pozadia"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr "Pridajte nové pozadie to zoznamu. Pošlite platný obrázok"
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr "Ak chcete odobrať neaké pozadia, použite nasledujúci prehliadač "
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr "Nastavte upozornenie domovskej stránky pre všetkých užívateľov, napríklad varovanie, dôležitý oznam alebo reklamu."
+
+msgid "Simple notice"
+msgstr "Jednoduché upozornenie"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr "Toto oznámenie vyžaduje iba jednoduchý text, a žiaden kód nie je povolený"
+
+msgid "Advanced notice"
+msgstr "Pokročilé oznámenie"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr "Vaše upozornenie môžete upraviť pomocou embedded HTML, CSS a JavaScriptom, ale musíte nakódovať stýl."
+
+msgid "Available updates"
+msgstr "Dostupné aktualizácie"
+
+msgid "What's new?"
+msgstr "Čo je nové?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "Vaša zložka na ukladanie nemá povolený zápis, upravte oprávnenia"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr "%1s môže spôsobiť problémy s proxy, zvýšte hodnotu %2s na %3s!"
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Práve používate vývojovú verziu. Aktualizujte ju prostredníctvom nášho repozitáru spustením: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "Dostupná nová verzia Jappix! Skontrolujte čo je nové a spustite update!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Vaša verzia je neaktuálna. Aktualizujte ju na %s kliknutím sem!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Vaša verzia sa zdá byť aktuálna, ale môžete skontrolovať aktualizácie kliknutím sem."
+
+msgid "Check for updates"
+msgstr "Skontrolovať aktualizácie"
+
+msgid "Update in progress"
+msgstr "Prebieha aktualizácia"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix bol aktualizovaný: práve používate najnovšiu verziu. Bavte sa!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Aktualizácia zlyhala! Skúste to neskôr prosím."
+
+msgid "Downloading package..."
+msgstr "Preberanie balíku.."
+
+msgid "Removing current Jappix system files..."
+msgstr "Odstraňovanie súčastných systémových súborov Jappixu.."
+
+msgid "Extracting package..."
+msgstr "Rozbaľovanie balíku..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "Regenerovanie storage folder tree..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix je aktualizovaný!"
+
+msgid "Aborted: socket error!"
+msgstr "Prerušené: socket error!"
+
+msgid "Aborted: buffer error!"
+msgstr "Prerušené: buffer error!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "Prerušené: everything is not writable!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "Prerušené: nedá sa rozbaliť balík!"
+
+msgid "Visits"
+msgstr "Návštevnosť"
+
+msgid "Daily"
+msgstr "Denne"
+
+msgid "Weekly"
+msgstr "Týždenne"
+
+msgid "Monthly"
+msgstr "Mesačne"
+
+msgid "Yearly"
+msgstr "Ročne"
+
+msgid "Size"
+msgstr "Veľkosť"
+
+msgid "Clean everything"
+msgstr "Vyčisti všetko"
+
+msgid "Purge cache"
+msgstr "Zbaviť sa cache"
+
+msgid "Purge logs"
+msgstr "Zbaviť sa logov"
+
+msgid "Purge updates"
+msgstr "Zbaviť sa aktualizácii"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "Odkladací priestor, ktorý ste chceli vyčistiť je teraz prázdny!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "Udržujte váš Jappix uzol čerstvý a rýchly, čistite pravidelne odkladací priestor!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "Nahrajte svoju hudbu (Ogg Vorbis, MP3 alebo WAV) a môžte ju počúvať v Jappixe!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "Súbor, ktorý chcete nahrať musí byť menší ako %s."
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr "Zostaňte v obraze o tom čo vaši užívatelia ukladajú na váš server a odstráňte neželaný obsah pomocou tohto nástroja"
+
+msgid "Title"
+msgstr "Titul"
+
+msgid "Artist"
+msgstr "Umelec"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Súbor"
+
+msgid "Upload"
+msgstr "Nahrať"
+
+msgid "The folder is empty."
+msgstr "Zložka je prázdna"
+
+msgid "The music could not be received, please retry!"
+msgstr "Hudbu sa nepodarilo prevziať, prosím skúste znova!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "Toto nie je platný hudobný súbor. konvertujte ho na Ogg Vorbis, MP3 alebo WAV!"
+
+msgid "Your music has been added!"
+msgstr "Vaša hudba bola pridaná!"
+
+msgid "The selected elements have been removed."
+msgstr "Vybrané položky budú odstránené."
+
+msgid "You must select elements to remove!"
+msgstr "Musíte vybrať položky na odstránenie!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "Pridaj užívateľa alebo zmeň heslo (zadaj existujuce užívateľské meno). Zvoľte silné heslo!"
+
+msgid "Manage"
+msgstr "Spravovať"
+
+msgid "List"
+msgstr "Zoznam"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "Odstráň užívateľa, Pamätajte že nemôžete odstrániť užívateľa ak je posledný."
+
+msgid "The user has been added!"
+msgstr "Užívateľ bol pridaný"
+
+msgid "The chosen users have been removed."
+msgstr "Vybraný užívateľ bol odstránený."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Musíte vybrať jedného alebo viacerých užívateľov pre odstránenie!"
+
+msgid "Yesterday"
+msgstr "Včera"
+
+msgid "%s days ago"
+msgstr "Pred %s dňami"
+
+msgid "User currently active"
+msgstr "Užívateľ je aktívny"
+
+msgid "Last seen: %s"
+msgstr "Naposledy videný: %s"
+
+msgid "Inactive since: %s"
+msgstr "Neaktívny od: %s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "Zdá sa že váš priateľ nedostal nedostal vašu správu(y)!"
+
+msgid "Static content server"
+msgstr "Static content server"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "Toto je statický obsah serveru pre %1s, “%2s”."
+
+msgid "Suggested friends"
+msgstr "Navrhovaní priatelia"
+
+msgid "Check all"
+msgstr "Označit všetko"
+
+msgid "Uncheck all"
+msgstr "Odznačit všetko"
+
+msgid "Choose"
+msgstr "Zvoliť"
+
+msgid "List name"
+msgstr "Meno zoznamu"
+
+msgid "Allow"
+msgstr "Povoliť"
+
+msgid "Deny"
+msgstr "Zamietnuť"
+
+msgid "Group"
+msgstr "Skupina"
+
+msgid "Subscription"
+msgstr "Odoberanie"
+
+msgid "Both"
+msgstr "Obe"
+
+msgid "From"
+msgstr "Od"
+
+msgid "Everybody"
+msgstr "Všetci"
+
+msgid "Send messages"
+msgstr "Poslať správu"
+
+msgid "Send queries"
+msgstr "Send queries"
+
+msgid "See my status"
+msgstr "Zobraziť môj status"
+
+msgid "Send his/her status"
+msgstr "Odoslať jeho-jej status"
+
+msgid "Everything"
+msgstr "Všetko"
+
+msgid "Item"
+msgstr "Položka"
+
+msgid "Order"
+msgstr "Poradie"
+
+msgid "Active for this session"
+msgstr "Aktívny pre toto sedenie"
+
+msgid "Always active"
+msgstr "Vždy aktívny"
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr "Vyhľadať priateľa"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr "Jappix je nezisková sociálna platforma, ku ktorej máte prístup kdekoľvek, kedykoľvek chcete a s kýmkoľvek chcete komunikovať"
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/sv/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/sv/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..5d65924
Binary files /dev/null and b/jappixmini/jappix/lang/sv/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/sv/LC_MESSAGES/main.po b/jappixmini/jappix/lang/sv/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..d791018
--- /dev/null
@@ -0,0 +1,1870 @@
+# Swedish translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "Jappix kräver Javascript för att fungera, men det saknas eller är avstängt i din webbläsare."
+
+msgid "An open social network"
+msgstr "Ett öppet socialt nätverk."
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix har blivit avbryten av ett nätverksproblem, en bugg eller felaktiga loginuppgifter (se till att du har skrivit rätt uppgifter), Vi ber om ursäkt för besväret."
+
+msgid "The element list on this server could not be obtained!"
+msgstr "Elementlistan på denna server kunde inte hämtas!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Ditt lösenord har ändrats, du kan nu logga in med det."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Ditt XMPP konto har blivit borttaget. Hejdå!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "Du har blivit utloggad från ditt XMPP konto. Ha en bra dag!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Rummet du har gått med i verkar inte existera. Skapa det!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "Gruppchatten har blivit borttagen. Nu kan någon annan återskapa den."
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Användaren som du vill nå är inte närvarande i detta rum."
+
+msgid "Please enter the group chat address to join."
+msgstr "Var god skriv in gruppchat adressen du vill gå med i."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Var god skriv in ditt användarnamn för att gå med i %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Rummet (%s) är lösenordskyddat."
+
+msgid "Your browser is out of date!"
+msgstr "Din webbläsare är för gammal!"
+
+msgid "Last %s version is better!"
+msgstr "Versionen &s är bättre!"
+
+msgid "Login"
+msgstr "Logga in"
+
+msgid "Register"
+msgstr "Registrera"
+
+msgid "Here we go!"
+msgstr "Sätt igång!"
+
+msgid "Server"
+msgstr "Server"
+
+msgid "Password"
+msgstr "Lösenord"
+
+msgid "Remember me"
+msgstr "Kom ihåg mig"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Detta verktyg är inaktiverat, du kan inte använda det!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "På grund av ett nätverksproblem så har du blivit frånkopplad. Vad vill du göra nu?"
+
+msgid "Reconnect"
+msgstr "Återanslut"
+
+msgid "Messages"
+msgstr "Meddelanden"
+
+msgid "Profile"
+msgstr "Profil"
+
+msgid "Options"
+msgstr "Inställningar"
+
+msgid "Disconnect"
+msgstr "Koppla ner"
+
+msgid "Filter"
+msgstr "Filtrera"
+
+msgid "Add a friend"
+msgstr "Lägg till en vän"
+
+msgid "Your groupchats"
+msgstr "Dina gruppchatter"
+
+msgid "Manage your favorite groupchats"
+msgstr "Hantera dina favorit gruppchatter"
+
+msgid "More stuff"
+msgstr "Fler verktyg"
+
+msgid "Show all friends"
+msgstr "Visa alla vänner"
+
+msgid "Only show connected friends"
+msgstr "Visa bara anslutna vänner"
+
+msgid "Message archives"
+msgstr "Meddelandearkiv"
+
+msgid "Date"
+msgstr "Datum"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Var god välj en vän för att se chathistoriken."
+
+msgid "Nothing found for: %s"
+msgstr "Inget hittades med: %s"
+
+msgid "A short message?"
+msgstr "Kort meddelande?"
+
+msgid "How are you?"
+msgstr "Hur mår du?"
+
+msgid "What are you doing?"
+msgstr "Vad gör du?"
+
+msgid "Join a chat"
+msgstr "Gå med i en chat"
+
+msgid "Status"
+msgstr "Tillstånd"
+
+msgid "Available"
+msgstr "Tillgänglig"
+
+msgid "Talkative"
+msgstr "Pratsam"
+
+msgid "Away"
+msgstr "Borta"
+
+msgid "Not available"
+msgstr "Ej tillgänglig"
+
+msgid "Busy"
+msgstr "Uppagen"
+
+msgid "Mood"
+msgstr "Humör"
+
+msgid "None"
+msgstr "Inget"
+
+msgid "Crazy"
+msgstr "Galen"
+
+msgid "Excited"
+msgstr "Upphetsad"
+
+msgid "Playful"
+msgstr "Lekfull"
+
+msgid "Happy"
+msgstr "Glad"
+
+msgid "Shocked"
+msgstr "Chockad"
+
+msgid "Hot"
+msgstr "Het"
+
+msgid "Sad"
+msgstr "Ledsen"
+
+msgid "Amorous"
+msgstr "Förälskad"
+
+msgid "Confident"
+msgstr "Självsäker"
+
+msgid "Activity"
+msgstr "Aktivitet"
+
+msgid "Chores"
+msgstr "Sysslor"
+
+msgid "Drinking"
+msgstr "Dricker"
+
+msgid "Eating"
+msgstr "Äter"
+
+msgid "Exercising"
+msgstr "Tränar"
+
+msgid "Grooming"
+msgstr "Förbereder"
+
+msgid "Appointment"
+msgstr "På möte"
+
+msgid "Inactive"
+msgstr "Inaktiv"
+
+msgid "Relaxing"
+msgstr "Slappnar av"
+
+msgid "Talking"
+msgstr "Pratar"
+
+msgid "Traveling"
+msgstr "Reser"
+
+msgid "Working"
+msgstr "Jobbar"
+
+msgid "View profile"
+msgstr "Visa profil"
+
+msgid "Repeat this notice"
+msgstr "Repetera notis"
+
+msgid "Remove this notice"
+msgstr "Radera notis"
+
+msgid "Your profile"
+msgstr "Din profil"
+
+msgid "Identity"
+msgstr "Identitet"
+
+msgid "Profile image"
+msgstr "Profilbild"
+
+msgid "Others"
+msgstr "Andra"
+
+msgid "Personal"
+msgstr "Personliga"
+
+msgid "Complete name"
+msgstr "Fullständigt namn"
+
+msgid "Nickname"
+msgstr "Smeknamn"
+
+msgid "First name"
+msgstr "Förnamn"
+
+msgid "Last name"
+msgstr "Efternamn"
+
+msgid "Date of birth"
+msgstr "Födelsedatum"
+
+msgid "Contact"
+msgstr "Kontakt"
+
+msgid "E-mail"
+msgstr "E-post"
+
+msgid "Phone"
+msgstr "Telefon nummer"
+
+msgid "Website"
+msgstr "Hemsida"
+
+msgid "Current"
+msgstr "Nuvarande"
+
+msgid "Delete"
+msgstr "Radera"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Vad synd! Du har ingen profilbild för ditt identitetskort!"
+
+msgid "Address"
+msgstr "Address"
+
+msgid "Street"
+msgstr "Gata"
+
+msgid "City"
+msgstr "Stad"
+
+msgid "Postal code"
+msgstr "Postnummer"
+
+msgid "Country"
+msgstr "Land"
+
+msgid "Biography"
+msgstr "Biografi"
+
+msgid "Important notice"
+msgstr "Viktigt meddelande"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Var försiktig med informationen du skriver in i din profil, det kan läsas av alla (till och med någon du inte vill ska se)."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Allting är inte privat på XMPP, detta är en av sakerna. Din offentliga profil (vCard)."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "Det är rekommenderat att ladda upp en profilbild (max %s), som en bild på dig själv. Det gör det lätt att identifieras av dina vänner."
+
+msgid "Save"
+msgstr "Spara"
+
+msgid "Cancel"
+msgstr "Avbryt"
+
+msgid "Edit options"
+msgstr "Ändra inställningar"
+
+msgid "Channel"
+msgstr "Kanal"
+
+msgid "Commands"
+msgstr "Kommandon"
+
+msgid "Sounds"
+msgstr "Ljud"
+
+msgid "Privacy"
+msgstr "Integritet"
+
+msgid "Message archiving"
+msgstr "Meddelande arkivering"
+
+msgid "Store a history of your chats"
+msgstr "Spara en historik av dina chatter"
+
+msgid "Geolocation"
+msgstr "Geolocation"
+
+msgid "Empty"
+msgstr "Tom"
+
+msgid "Empty channel"
+msgstr "Tom kanal"
+
+msgid "Persistent"
+msgstr "Beständig"
+
+msgid "Maximum notices"
+msgstr "Maximalt antal notiser"
+
+msgid "Account"
+msgstr "Konto"
+
+msgid "Change password"
+msgstr "Ändra lösenord"
+
+msgid "Delete account"
+msgstr "Ta bort konto"
+
+msgid "Old"
+msgstr "Gammal"
+
+msgid "New (2 times)"
+msgstr "Ny"
+
+msgid "Continue"
+msgstr "Fortsätt"
+
+msgid "To"
+msgstr "Till"
+
+msgid "Close"
+msgstr "Stäng"
+
+msgid "unknown"
+msgstr "okänd"
+
+msgid "Unavailable"
+msgstr "Otillgänglig"
+
+msgid "is now"
+msgstr "är nu"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "Var god vänta medans din profilbild uppladdas..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Där är den! En ny vacker profilbild!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Bildfilen stödjs ej eller har en ogiltlig storlek."
+
+msgid "Reply"
+msgstr "Svara"
+
+msgid "Error"
+msgstr "Fel"
+
+msgid "Click here to solve the error"
+msgstr "Klicka här för att lösa problemet"
+
+msgid "You"
+msgstr "Du"
+
+msgid "Remove"
+msgstr "Ta bort"
+
+msgid "Rename"
+msgstr "Byt namn"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Hej, Jag är %s och jag skulle vilja lägga till dig som min vän."
+
+msgid "Smiley insertion"
+msgstr "Smiley inläggning"
+
+msgid "Change style"
+msgstr "Ändra stil"
+
+msgid "Text in bold"
+msgstr "Bred text"
+
+msgid "Text in italic"
+msgstr "Kursiv text"
+
+msgid "Underlined text"
+msgstr "Understruken text"
+
+msgid "Save chat"
+msgstr "Spara chat"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "Trycka på denna länk för att få chatloggen och vänta. Tryck sedan igen för att få filen."
+
+msgid "This chat is empty!"
+msgstr "Denna chat är tom!"
+
+msgid "Generate file!"
+msgstr "Generera fil!"
+
+msgid "Download file!"
+msgstr "Ladda ner fil!"
+
+msgid "Clean current chat"
+msgstr "Rensa nuvarande chat"
+
+msgid "View chat history"
+msgstr "Visa chathistorik"
+
+msgid "Show user profile"
+msgstr "Visa användarprofil"
+
+msgid "Add this contact to your friends"
+msgstr "Lägg till denna kontakt till dina vänner"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Lägg till denna gruppchat till dina favoriter"
+
+msgid "All tabs"
+msgstr "Alla flikar"
+
+msgid "Close this tab"
+msgstr "Stäng denna flik"
+
+msgid "no subject defined for this room."
+msgstr "inget ämne satt i detta rum."
+
+msgid "Administration panel for this room"
+msgstr "Administrationspanel för detta rum"
+
+msgid "Moderators"
+msgstr "Moderatorer"
+
+msgid "Participants"
+msgstr "Deltagare"
+
+msgid "Visitors"
+msgstr "Besökare"
+
+msgid "Manage favorite rooms"
+msgstr "Hantera favoritrum"
+
+msgid "Change favorites"
+msgstr "Ändra favoriter"
+
+msgid "Search a room"
+msgstr "Sök efter ett rum"
+
+msgid "Select a favorite"
+msgstr "Välj en favorit"
+
+msgid "Getting the name..."
+msgstr "Få tag i namn..."
+
+msgid "Gateway"
+msgstr "Gateway"
+
+msgid "Name"
+msgstr "Namn"
+
+msgid "Room"
+msgstr "Rum"
+
+msgid "Add"
+msgstr "Lägg till"
+
+msgid "Edit"
+msgstr "Ändra"
+
+msgid "Search a room on"
+msgstr "Sök efter ett rum på"
+
+msgid "No room found on this server."
+msgstr "Inget rum hittat på denna server."
+
+msgid "Service discovery"
+msgstr "Tjänst upptäckande"
+
+msgid "Server to query"
+msgstr "Server att ifrågesätta"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "Ursäkta, men föremålet lämnade inga resultat!"
+
+msgid "Accounts"
+msgstr "Konton"
+
+msgid "Authentications"
+msgstr "Autentiseringar"
+
+msgid "Automation"
+msgstr "Automatik"
+
+msgid "Clients"
+msgstr "Klienter"
+
+msgid "Collaboration"
+msgstr "Kollaboration"
+
+msgid "Components"
+msgstr "Komponenter"
+
+msgid "Rooms"
+msgstr "Rum"
+
+msgid "Directories"
+msgstr "Kataloger"
+
+msgid "Gateways"
+msgstr ""
+
+msgid "News"
+msgstr "Nyheter"
+
+msgid "Hierarchy"
+msgstr "Hierarki"
+
+msgid "Proxies"
+msgstr ""
+
+msgid "Publication/Subscription"
+msgstr "Publicering/Prenumeration"
+
+msgid "Storage"
+msgstr "Lagring"
+
+msgid "Service offline or broken"
+msgstr "Tjänsten är ur funktion"
+
+msgid "Your inbox"
+msgstr "Din inkorg"
+
+msgid "Available actions"
+msgstr ""
+
+msgid "Clean"
+msgstr "Rensa"
+
+msgid "New"
+msgstr "Ny"
+
+msgid "Received"
+msgstr "Mottagen"
+
+msgid "Subject"
+msgstr "Ämne"
+
+msgid "Content"
+msgstr "Innehåll"
+
+msgid "Send message"
+msgstr "Skicka meddelande"
+
+msgid "Your inbox is empty."
+msgstr "Din inkorg är tom."
+
+msgid "MUC administration"
+msgstr ""
+
+msgid "You administrate this room"
+msgstr "Du administrerar detta rum"
+
+msgid "Enter new subject"
+msgstr "Ange nytt ämne"
+
+msgid "Configuration"
+msgstr "Inställningar"
+
+msgid "Authorizations"
+msgstr "Tillåtelser"
+
+msgid "Member list"
+msgstr "Medlemslista"
+
+msgid "Owner list"
+msgstr "Ägarlista"
+
+msgid "Administrator list"
+msgstr "Administratörslista"
+
+msgid "Outcast list"
+msgstr "Lista på uteslutna"
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr ""
+
+msgid "Yes, let's do it!"
+msgstr "Ja, kör på!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr ""
+
+msgid "Your friend is writing a message..."
+msgstr "Din vän skriver..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Din vän slutade skriva."
+
+msgid "Your friend is doing something else."
+msgstr ""
+
+msgid "Your friend closed the chat."
+msgstr ""
+
+msgid "Requesting this service..."
+msgstr ""
+
+msgid "Loading"
+msgstr "Startar"
+
+msgid "joined the chat room"
+msgstr "kom in i rummet"
+
+msgid "left the chat room"
+msgstr "lämnade rummet"
+
+msgid "no status"
+msgstr "ingen status"
+
+msgid "has been kicked"
+msgstr "har sparkats ut"
+
+msgid "has been banned"
+msgstr "har utestängts"
+
+msgid "no reason"
+msgstr "ingen anledning"
+
+msgid "Communicate with the entire world!"
+msgstr "Kommunicera med hela världen!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr "Hej där!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "Välkommen till %1s, “%2s”."
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr "Föregående"
+
+msgid "General"
+msgstr "Allmänt"
+
+msgid "Advanced"
+msgstr "Avancerat"
+
+msgid "Resource"
+msgstr "Resurs"
+
+msgid "Priority"
+msgstr "Prioritet"
+
+msgid "Low"
+msgstr "Låg"
+
+msgid "Medium"
+msgstr "Medium"
+
+msgid "High"
+msgstr "Hög"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr "inloggningssida"
+
+msgid "Share this link with your friends:"
+msgstr "Skicka denna länk till dina vänner:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr "Obligatorisk"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "Du har registrertats. Din XMPP-adress är:"
+
+msgid "Manager"
+msgstr ""
+
+msgid "Project"
+msgstr "Projekt"
+
+msgid "Encrypted"
+msgstr "Krypterad"
+
+msgid "Unencrypted"
+msgstr "Okrypterad"
+
+msgid "Where are you?"
+msgstr "Var är du?"
+
+msgid "What's up with you?"
+msgstr "Hur är läget?"
+
+msgid "Fetching the social channel..."
+msgstr "Hämtar den sociala kanalen..."
+
+msgid "You are synchronized with your network."
+msgstr ""
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr ""
+
+msgid "Media viewer"
+msgstr "Mediavisare"
+
+msgid "Browse"
+msgstr "Bläddra"
+
+msgid "Command"
+msgstr "Kommando"
+
+msgid "Subscribe"
+msgstr "Prenumerera"
+
+msgid "Join"
+msgstr "Gå med"
+
+msgid "Automatic"
+msgstr "Automatiskt"
+
+msgid "Search"
+msgstr "Sök"
+
+msgid "No result!"
+msgstr "Inget resultat!"
+
+msgid "No notifications."
+msgstr ""
+
+msgid "would like to add you as a friend."
+msgstr "vill lägga til dig som en vän."
+
+msgid "would like you to join this chatroom:"
+msgstr "vill att du går med i detta chattrum:"
+
+msgid "Do you accept?"
+msgstr "Vill du acceptera inbjudan?"
+
+msgid "Yes"
+msgstr "Ja"
+
+msgid "No"
+msgstr "Nej"
+
+msgid "would like to get authorization."
+msgstr "vill få tillåtelse."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr "Skicka"
+
+msgid "Client"
+msgstr "Klient"
+
+msgid "System"
+msgstr "System"
+
+msgid "Local time"
+msgstr "Lokal tid"
+
+msgid "Comments"
+msgstr "Kommentarer"
+
+msgid "User profile"
+msgstr "Användarprofil"
+
+msgid "See his/her position on the globe"
+msgstr "Se hans/hennes position på jordklotet"
+
+msgid "Confirm"
+msgstr "Bekräfta"
+
+msgid "anonymous mode"
+msgstr "anonymt läge"
+
+msgid "Groups"
+msgstr "Grupper"
+
+msgid "Unclassified"
+msgstr "Oklassificerad"
+
+msgid "Authorize"
+msgstr "Tillåtelse"
+
+msgid "Ask for authorization"
+msgstr "Be om tillåtelse"
+
+msgid "Unblock"
+msgstr "Avblockera"
+
+msgid "Prohibit"
+msgstr "Förhindra"
+
+msgid "Block"
+msgstr "Blockera"
+
+msgid "Chat"
+msgstr "Chatt"
+
+msgid "Groupchat"
+msgstr "Gruppchatt"
+
+msgid "Jappix Mobile"
+msgstr "Jappix Mobilt"
+
+msgid "Desktop"
+msgstr "Skrivbord"
+
+msgid "Mobile"
+msgstr "Mobilt"
+
+msgid "Please wait..."
+msgstr "Var god vänta..."
+
+msgid "Please enable JavaScript"
+msgstr "Vänligen aktivera JavaScript"
+
+msgid "Your channel"
+msgstr "Din kanal"
+
+msgid "Channel of"
+msgstr ""
+
+msgid "More notices..."
+msgstr "Fler notiser..."
+
+msgid "Attach a file"
+msgstr "Bifoga en fil"
+
+msgid "Send"
+msgstr "Skicka"
+
+msgid "Unattach the file"
+msgstr "Ta bort bifogad fil"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "Ett fel uppstod vid uppladdning. Kanske filen är större än %s eller av blockerad av någon anledning."
+
+msgid "Authorization failed"
+msgstr "Tillåtelsekontroll misslyckades"
+
+msgid "Registration failed, please choose a different username"
+msgstr "Registrering misslyckades. Vänligen välj ett annat användarnamn"
+
+msgid "Service unavailable"
+msgstr "Tjänsten ej tillgänglig"
+
+msgid "Internal server error, try later"
+msgstr "Internt serverfel. Försök gärna senare"
+
+msgid "Your form has been sent."
+msgstr "Ditt formulär har skickats."
+
+msgid "Application"
+msgstr ""
+
+msgid "XMPP links"
+msgstr "XMPP-länkar"
+
+msgid "Open XMPP links with Jappix"
+msgstr "Öppna XMPP-länkar med Jappix"
+
+msgid "changed the subject to:"
+msgstr "ändrade ämnet till:"
+
+msgid "Welcome!"
+msgstr "Välkommen!"
+
+msgid "Friends"
+msgstr "Vänner"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr "Aktivera ljudeffekter"
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr "Ej inloggade vänner"
+
+msgid "Don't hide offline friends"
+msgstr "Visa även ej inloggade vänner"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "Använder Jappix, en öppen social plattform. Jag är %s!"
+
+msgid "Unknown name"
+msgstr "Okänt namn"
+
+msgid "Unknown country"
+msgstr "Okänt land"
+
+msgid "Click to enable"
+msgstr "Klicka för att aktivera"
+
+msgid "Click to disable"
+msgstr "Klicka för att deaktivera"
+
+msgid "Installation"
+msgstr "Installation"
+
+msgid "Jappix installation"
+msgstr "Installera Jappix"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "Välkommen till installationen av Jappix!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr "Välkommen"
+
+msgid "Storage configuration"
+msgstr "Konfigurera lagring"
+
+msgid "Administrator account"
+msgstr "Administratörskonto"
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr "Inställningar för värdar"
+
+msgid "Services installation"
+msgstr "Installation av tjänster"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr "Mappen är skrivbar -- du kan nu fortsätta!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "Oops, något saknas, eller så matchar inte de två lösenorden!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr "Användare"
+
+msgid "Service"
+msgstr "Tjänst"
+
+msgid "Service name"
+msgstr "Tjänstnamn"
+
+msgid "Service description"
+msgstr "Tjänstbeskrivning"
+
+msgid "Connection"
+msgstr "Anslutning"
+
+msgid "Lock the host"
+msgstr "Lås värd"
+
+msgid "Anonymous mode"
+msgstr "Anonymt läge"
+
+msgid "Registration allowed"
+msgstr "Registrering tillåten"
+
+msgid "Use a proxy"
+msgstr "Använd en proxy"
+
+msgid "Encryption"
+msgstr "Kryptering"
+
+msgid "HTTPS storage"
+msgstr "Lagring HTTPS"
+
+msgid "Force HTTPS"
+msgstr "Kräv HTTPS"
+
+msgid "Compression"
+msgstr "Komprimering"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr "Huvudvärd"
+
+msgid "Groupchat host"
+msgstr "Värd för gruppchatt"
+
+msgid "Anonymous host"
+msgstr "Anonym värd"
+
+msgid "Directory host"
+msgstr "Katalogvärd"
+
+msgid "BOSH host"
+msgstr "BOSH värd"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr "Tack för att du använder Jappix!"
+
+msgid "Next"
+msgstr "Nästa"
+
+msgid "Finish"
+msgstr "Slutför"
+
+msgid "Check again"
+msgstr "Kontrollera igen"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "Mappen är ej skrivbar. Korrigera rättigheterna för mappen %s"
+
+msgid "%s is installed on your system."
+msgstr "%s har installerats på ditt system."
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s har ej installerats på ditt system. Du borde installera %2s."
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "Maxgränsen för uppladdning via PHP är tillräcklig (%s)."
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "Maxgränsen för uppladdning via PHP är ej tillräcklig (%1s). Du bör ange gränsen till %2s i %3s."
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr "Statistik"
+
+msgid "Hosts"
+msgstr "Värdar"
+
+msgid "Design"
+msgstr "Utseende"
+
+msgid "Repeat"
+msgstr "Repetera"
+
+msgid "All"
+msgstr "Alla"
+
+msgid "Horizontal"
+msgstr "Sidled"
+
+msgid "Vertical"
+msgstr "Höjdled"
+
+msgid "Center"
+msgstr "Mitten"
+
+msgid "Left"
+msgstr "Vänster"
+
+msgid "Right"
+msgstr "Höger"
+
+msgid "Top"
+msgstr "Toppen"
+
+msgid "Bottom"
+msgstr "Botten"
+
+msgid "Adapt"
+msgstr "Anpassa"
+
+msgid "Color"
+msgstr "Färg"
+
+msgid "Users"
+msgstr "Användare"
+
+msgid "Updates"
+msgstr "Uppdateringar"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "Vänligen använd formuläret nedan för att logga in på administratörsbilden."
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr "Rättigheter"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "Du har nu loggats ut. Hej då!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "Oops, du verkar inte ha administratörsrättigheter. Kontrollera dina rättigheter."
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "Ej giltig bild. Vänligen använd enbart bilder i format PNG, GIF eller JPG."
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "Bilden kunde inte tas emot. Det kanske hjälper att försöka igen."
+
+msgid "Your image was added to the list!"
+msgstr "Din bild lades till i listan!"
+
+msgid "Changes saved!"
+msgstr "Ändringar sparade!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr "Januari"
+
+msgid "February"
+msgstr "Februari"
+
+msgid "March"
+msgstr "Mars"
+
+msgid "April"
+msgstr "April"
+
+msgid "May"
+msgstr "Maj"
+
+msgid "June"
+msgstr "Juni"
+
+msgid "July"
+msgstr "Juli"
+
+msgid "August"
+msgstr "Augusti"
+
+msgid "September"
+msgstr "September"
+
+msgid "October"
+msgstr "Oktober"
+
+msgid "November"
+msgstr "November"
+
+msgid "December"
+msgstr "December"
+
+msgid "Monday"
+msgstr "Måndag"
+
+msgid "Tuesday"
+msgstr "Tisdag"
+
+msgid "Wednesday"
+msgstr "Onsdag"
+
+msgid "Thursday"
+msgstr "Torsdag"
+
+msgid "Friday"
+msgstr "Fredag"
+
+msgid "Saturday"
+msgstr "Lördag"
+
+msgid "Sunday"
+msgstr "Söndag"
+
+msgid "Total"
+msgstr "Totalt"
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr "Musik"
+
+msgid "Backgrounds"
+msgstr "Bakgrunder"
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr "Bakgrund"
+
+msgid "Notice"
+msgstr "Notis"
+
+msgid "Your design preferences have been saved!"
+msgstr "Dina inställningar för utseendet har sparats!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "Vänligen kontrollera indata -- någonting saknas!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr "Använd standardbakgrunden"
+
+msgid "Use your own image"
+msgstr "Använd egen bild"
+
+msgid "Select a background to use and change the display options."
+msgstr "Välj en bakgrund och ändra inställningar för utseendet."
+
+msgid "Use your own color"
+msgstr "Använd egen färg"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "Ange det hexadecimala värdet (webbfärgvärdet) för den färg du vill använda som bakgrund."
+
+msgid "Manage backgrounds"
+msgstr "Anpassa bakgrunder"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr "Tillgängliga uppdateringar"
+
+msgid "What's new?"
+msgstr "Vad är nytt?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "Du använder utvecklingsversionen av Jappix. Den uppdateras genom vårt repo genom att köra: %s."
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "En ny version av Jappix finns tillgänglig! Kontrollera vad som är nytt och starta uppdateringen."
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "Din version är gammal. Uppdatera till %s nu genom att klicka här!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "Din version verkar vara aktuell, men du kan kontrollera uppdateringar manuellt genom att klicka här."
+
+msgid "Check for updates"
+msgstr "Sök efter uppdateringar"
+
+msgid "Update in progress"
+msgstr "Uppdaterar"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix har uppdaterats. Du använder nu den senaste versionen. Varsågod!"
+
+msgid "The update has failed! Please try again later."
+msgstr "Uppdateringen misslyckades. Vänligen försök igen senare."
+
+msgid "Downloading package..."
+msgstr "Laddar ned.."
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix är nu uppdaterad!"
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr "Besök"
+
+msgid "Daily"
+msgstr "Dagligen"
+
+msgid "Weekly"
+msgstr "Veckovis"
+
+msgid "Monthly"
+msgstr "Månatligen"
+
+msgid "Yearly"
+msgstr "Årsvis"
+
+msgid "Size"
+msgstr "Storlek"
+
+msgid "Clean everything"
+msgstr "Rensa allt"
+
+msgid "Purge cache"
+msgstr "Rensa cache"
+
+msgid "Purge logs"
+msgstr "Rensa loggar"
+
+msgid "Purge updates"
+msgstr "Rensa uppdateringar"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr "Titel"
+
+msgid "Artist"
+msgstr "Artist"
+
+msgid "Album"
+msgstr "Album"
+
+msgid "File"
+msgstr "Fil"
+
+msgid "Upload"
+msgstr "Ladda upp"
+
+msgid "The folder is empty."
+msgstr "Mappen är tom."
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr "Hantera"
+
+msgid "List"
+msgstr "Lista"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr "Användaren har lagts till!"
+
+msgid "The chosen users have been removed."
+msgstr "De valda användarna har tagits bort."
+
+msgid "You must select one or more users to be removed!"
+msgstr "Välj en eller flera användare som ska tas bort!"
+
+msgid "Yesterday"
+msgstr "Igår"
+
+msgid "%s days ago"
+msgstr "%s dagar sedan"
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr "Markera alla"
+
+msgid "Uncheck all"
+msgstr "Avmarkera alla"
+
+msgid "Choose"
+msgstr "Välj"
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr "Tillåt"
+
+msgid "Deny"
+msgstr "Förbjud"
+
+msgid "Group"
+msgstr "Grupp"
+
+msgid "Subscription"
+msgstr "Prenumeration"
+
+msgid "Both"
+msgstr "Båda"
+
+msgid "From"
+msgstr "Från"
+
+msgid "Everybody"
+msgstr "Alla"
+
+msgid "Send messages"
+msgstr "Skicka meddelanden"
+
+msgid "Send queries"
+msgstr "Skicka frågor"
+
+msgid "See my status"
+msgstr "Se min status"
+
+msgid "Send his/her status"
+msgstr "Skicka hans/hennes status"
+
+msgid "Everything"
+msgstr "Allt"
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr "Ordning"
+
+msgid "Active for this session"
+msgstr "Aktiv för denna session"
+
+msgid "Always active"
+msgstr "Alltid aktiv"
+
+msgid "User directory"
+msgstr "Deltagarkatalog"
+
+msgid "Search a friend"
+msgstr "Sök en vän"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr "Laddar kommentarer..."
+
+msgid "Type your comment here..."
+msgstr "Skriv här..."
+
+msgid "Could not get the comments!"
+msgstr "Kunde ej hämta kommentarer!"
+
+msgid "Show comments"
+msgstr "Visa kommentarer"
+
+msgid "Send him/her a message"
+msgstr "Skicka honom/henne ett meddelande"
+
+msgid "Start a chat with him/her"
+msgstr "Öppna en chatt med honom/henne"
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr "Visa"
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr "Värd för pubsub"
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr "Logotyp"
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr "Detta är ej en giltig bild. Vänligen använd bildformatet PNG."
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr "Bildformatet för logotypen måste vara PNG. Om något fält lämnas tomt kommer loggan ej att ändras."
+
+msgid "Remove this logo"
+msgstr "Ta bort denna logotyp."
+
+msgid "View this logo"
+msgstr "Se denna logotyp"
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr "kunde ej ta emot din fil “%s”."
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr "Tillgängliga genvägar:"
+
+msgid "%s removes the chat logs"
+msgstr "%s tar bort chattloggar"
+
+msgid "%s joins a groupchat"
+msgstr "%s går med i en gruppchatt"
+
+msgid "%s closes the chat"
+msgstr "%s stänger chatten"
+
+msgid "%s shows the user profile"
+msgstr "%s visar användarprofil"
+
+msgid "%s sends a message to the room"
+msgstr "%s skickar ett meddelande till (alla i) rummet"
+
+msgid "%s changes your nickname"
+msgstr "%s ändrar ditt chattnamn"
+
+msgid "%s sends a message to someone in the room"
+msgstr "%s skickar ett meddelande till någon i rummet"
+
+msgid "%s changes the room topic"
+msgstr "%s ändrar rummets ämnestext"
+
+msgid "%s kicks an user of the room"
+msgstr "%s sparkar ut en användare från rummet"
+
+msgid "%s bans an user of the room"
+msgstr "%s utesluter en användare från rummet"
+
+msgid "%s invites someone to join the room"
+msgstr "%s bjuder in någon att gå med i rummet"
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/uk/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/uk/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..78833b7
Binary files /dev/null and b/jappixmini/jappix/lang/uk/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/uk/LC_MESSAGES/main.po b/jappixmini/jappix/lang/uk/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..e5a39e0
--- /dev/null
@@ -0,0 +1,1870 @@
+# Ukrainian translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:25+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "У вашому браузері не активовано виконання JavaScript, тому Ви не зможете використовувати Jappix. Будь ласка, активуйте виконання JavaScript."
+
+msgid "An open social network"
+msgstr "Відкрита соціальна мережа"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Робота Jappix була перервана через проблеми зі зв'язком, помилку чи невірні дані користувача (перевірте логін та пароль), просимо вибачення за незручності."
+
+msgid "The element list on this server could not be obtained!"
+msgstr ""
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "Ваш пароль було змінено, тепер Ви можете увійти, використовуючи новий пароль."
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "Ваш акаунт було видалено."
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr ""
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "Кімнати, до якої ви приєднались, не існує. Ви повинні створити її."
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr ""
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "Користувач, з яким Ви намагаєтесь зв’язатися, відсутній у кімнаті."
+
+msgid "Please enter the group chat address to join."
+msgstr "Будьласка введіть адресу чату."
+
+msgid "Please enter your nickname to join %s."
+msgstr "Будь ласка, введіть ваш псевдонім щоб приєднатися до %s."
+
+msgid "This room (%s) is protected with a password."
+msgstr "Кімната %s захищена паролем."
+
+msgid "Your browser is out of date!"
+msgstr "Ваш браузер застарів!"
+
+msgid "Last %s version is better!"
+msgstr ""
+
+msgid "Login"
+msgstr "Вхід"
+
+msgid "Register"
+msgstr "Реєстрація"
+
+msgid "Here we go!"
+msgstr "Поїхали!"
+
+msgid "Server"
+msgstr "Сервер"
+
+msgid "Password"
+msgstr "Пароль"
+
+msgid "Remember me"
+msgstr "Запам’ятати мене"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "Цей інструмент був вимкнений, ви не можете використовувати його!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "Вас було від’єднано через проблеми з мережею. Що Ви хочете зробити тепер?"
+
+msgid "Reconnect"
+msgstr "Перепідключитись"
+
+msgid "Messages"
+msgstr "Повідомлення"
+
+msgid "Profile"
+msgstr "Профіль"
+
+msgid "Options"
+msgstr "Налаштування"
+
+msgid "Disconnect"
+msgstr "Від’єднатись"
+
+msgid "Filter"
+msgstr "Фільтр"
+
+msgid "Add a friend"
+msgstr "Додати друга"
+
+msgid "Your groupchats"
+msgstr "Ваша конференція"
+
+msgid "Manage your favorite groupchats"
+msgstr "Керування вашими улюбленими конференціями"
+
+msgid "More stuff"
+msgstr "Більше "
+
+msgid "Show all friends"
+msgstr "Показувати всіх друзів"
+
+msgid "Only show connected friends"
+msgstr "Показувати тільки під’єднаних друзів"
+
+msgid "Message archives"
+msgstr "Архів повідомлень"
+
+msgid "Date"
+msgstr "Дата"
+
+msgid "Please select a friend to view the chat history."
+msgstr "Будь ласка, виберіть друга для перегляду історії переписки."
+
+msgid "Nothing found for: %s"
+msgstr "Нічого не знайдено про %s"
+
+msgid "A short message?"
+msgstr "Коротке повідомлення?"
+
+msgid "How are you?"
+msgstr "Як ти?"
+
+msgid "What are you doing?"
+msgstr "Що ти робиш?"
+
+msgid "Join a chat"
+msgstr "Приєднатися до чату"
+
+msgid "Status"
+msgstr "Статус"
+
+msgid "Available"
+msgstr "Доступний"
+
+msgid "Talkative"
+msgstr "Говіркий"
+
+msgid "Away"
+msgstr "Відійшов"
+
+msgid "Not available"
+msgstr "Не доступний"
+
+msgid "Busy"
+msgstr "Зайнятий"
+
+msgid "Mood"
+msgstr "Настрій"
+
+msgid "None"
+msgstr "Нема"
+
+msgid "Crazy"
+msgstr "Божевільний"
+
+msgid "Excited"
+msgstr "Зацікавлений"
+
+msgid "Playful"
+msgstr "Грайливий"
+
+msgid "Happy"
+msgstr "Веселий"
+
+msgid "Shocked"
+msgstr "Шокований"
+
+msgid "Hot"
+msgstr "Гарячий"
+
+msgid "Sad"
+msgstr "Сумний"
+
+msgid "Amorous"
+msgstr "Закоханий"
+
+msgid "Confident"
+msgstr "Впевнений"
+
+msgid "Activity"
+msgstr "Діяльність"
+
+msgid "Chores"
+msgstr "Господарські роботи"
+
+msgid "Drinking"
+msgstr "П'ю"
+
+msgid "Eating"
+msgstr "Їм"
+
+msgid "Exercising"
+msgstr "Виконую вправи"
+
+msgid "Grooming"
+msgstr "Чепурюсь"
+
+msgid "Appointment"
+msgstr ""
+
+msgid "Inactive"
+msgstr "Неактивний"
+
+msgid "Relaxing"
+msgstr "Відпочиваю"
+
+msgid "Talking"
+msgstr "Розмовляю"
+
+msgid "Traveling"
+msgstr "Подорожую"
+
+msgid "Working"
+msgstr "Працюю"
+
+msgid "View profile"
+msgstr "Показати профіль"
+
+msgid "Repeat this notice"
+msgstr "Повторити нагадування"
+
+msgid "Remove this notice"
+msgstr "Видалити нагадування"
+
+msgid "Your profile"
+msgstr "Твій профіль"
+
+msgid "Identity"
+msgstr ""
+
+msgid "Profile image"
+msgstr "Аватар"
+
+msgid "Others"
+msgstr "Інші"
+
+msgid "Personal"
+msgstr "Персональні дані"
+
+msgid "Complete name"
+msgstr "Повне ім'я"
+
+msgid "Nickname"
+msgstr "Псевдонім"
+
+msgid "First name"
+msgstr "Ім'я"
+
+msgid "Last name"
+msgstr "Прізвище"
+
+msgid "Date of birth"
+msgstr "Дата народження"
+
+msgid "Contact"
+msgstr "Контакт"
+
+msgid "E-mail"
+msgstr ""
+
+msgid "Phone"
+msgstr "Телефон"
+
+msgid "Website"
+msgstr "Веб сайт"
+
+msgid "Current"
+msgstr "Поточні"
+
+msgid "Delete"
+msgstr "Видалити"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "Ви не вказали аватар в вашому профілі."
+
+msgid "Address"
+msgstr "Адреса"
+
+msgid "Street"
+msgstr "Вулиця"
+
+msgid "City"
+msgstr "Місто"
+
+msgid "Postal code"
+msgstr "Індекс"
+
+msgid "Country"
+msgstr "Країна"
+
+msgid "Biography"
+msgstr "Біографія"
+
+msgid "Important notice"
+msgstr "Важливі нагадування"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "Будьте обережні, інформація в вашому профілі доступна всім."
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "Не вся інформація приватна в XMPP; Ваш профіль - одна з цих речей."
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr ""
+
+msgid "Save"
+msgstr "Зберегти"
+
+msgid "Cancel"
+msgstr "Відмінити"
+
+msgid "Edit options"
+msgstr "Редагувати налаштування"
+
+msgid "Channel"
+msgstr "Канал"
+
+msgid "Commands"
+msgstr ""
+
+msgid "Sounds"
+msgstr "Музика"
+
+msgid "Privacy"
+msgstr "Приватність"
+
+msgid "Message archiving"
+msgstr "Архів повідомлень"
+
+msgid "Store a history of your chats"
+msgstr "зберігати історію ваших розмов"
+
+msgid "Geolocation"
+msgstr "Географічне положення"
+
+msgid "Empty"
+msgstr "Порожній"
+
+msgid "Empty channel"
+msgstr "Порожній канал"
+
+msgid "Persistent"
+msgstr "Наполегливий"
+
+msgid "Maximum notices"
+msgstr "Максимальна кількість нагадувань"
+
+msgid "Account"
+msgstr "Акаунт"
+
+msgid "Change password"
+msgstr "Змінити пароль"
+
+msgid "Delete account"
+msgstr "Видалити акаунт"
+
+msgid "Old"
+msgstr "Старий"
+
+msgid "New (2 times)"
+msgstr "Новий (2 рази)"
+
+msgid "Continue"
+msgstr "Продовжити"
+
+msgid "To"
+msgstr "До"
+
+msgid "Close"
+msgstr "Зачинити"
+
+msgid "unknown"
+msgstr "невідомий"
+
+msgid "Unavailable"
+msgstr "Не доступний"
+
+msgid "is now"
+msgstr "В даний час"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr ""
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "Ось вонін! Новий красивий аватар!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "Файл зображення не підтримується, або має неправильний розмір."
+
+msgid "Reply"
+msgstr "Відповісти"
+
+msgid "Error"
+msgstr "Помилка"
+
+msgid "Click here to solve the error"
+msgstr ""
+
+msgid "You"
+msgstr "Ти"
+
+msgid "Remove"
+msgstr "Видалити"
+
+msgid "Rename"
+msgstr "Перейменувати"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "Привіт я %s, хочу додати тебе до списку друзів."
+
+msgid "Smiley insertion"
+msgstr "Вставити смайл"
+
+msgid "Change style"
+msgstr "Змінити стиль"
+
+msgid "Text in bold"
+msgstr "жирний"
+
+msgid "Text in italic"
+msgstr "курсивний"
+
+msgid "Underlined text"
+msgstr "підкреслений"
+
+msgid "Save chat"
+msgstr "Зберегти бесіду"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr ""
+
+msgid "This chat is empty!"
+msgstr "Ця бесіда порожня!"
+
+msgid "Generate file!"
+msgstr "Створити файл!"
+
+msgid "Download file!"
+msgstr "Завантажити файл!"
+
+msgid "Clean current chat"
+msgstr "Очистити бесіду"
+
+msgid "View chat history"
+msgstr ""
+
+msgid "Show user profile"
+msgstr "Показати профіль користувача"
+
+msgid "Add this contact to your friends"
+msgstr "Додати цей контакт в друзі"
+
+msgid "Add this groupchat to your favorites"
+msgstr "Додати конференцію в улюблені"
+
+msgid "All tabs"
+msgstr "Всі вкладки"
+
+msgid "Close this tab"
+msgstr "Закрити цю вкладку"
+
+msgid "no subject defined for this room."
+msgstr "Не вказана тема для кімнати."
+
+msgid "Administration panel for this room"
+msgstr "Панель адміністрування для кімнати"
+
+msgid "Moderators"
+msgstr "Модератори"
+
+msgid "Participants"
+msgstr "Учасники"
+
+msgid "Visitors"
+msgstr "Відвідувачі"
+
+msgid "Manage favorite rooms"
+msgstr "Керування улюбленими кімнатами"
+
+msgid "Change favorites"
+msgstr "Змінити улюблені"
+
+msgid "Search a room"
+msgstr "Пошук кімнат"
+
+msgid "Select a favorite"
+msgstr "Оберіть улюблену"
+
+msgid "Getting the name..."
+msgstr "Отримання імені"
+
+msgid "Gateway"
+msgstr "Маршрутизатор"
+
+msgid "Name"
+msgstr "Ім'я"
+
+msgid "Room"
+msgstr "Кімната"
+
+msgid "Add"
+msgstr "Додати"
+
+msgid "Edit"
+msgstr "Редагувати"
+
+msgid "Search a room on"
+msgstr "Пошук кімнати на"
+
+msgid "No room found on this server."
+msgstr "Не знайдено кімнат на цьому сервері."
+
+msgid "Service discovery"
+msgstr "Пошук сервісів"
+
+msgid "Server to query"
+msgstr "запит на сервер"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr ""
+
+msgid "Accounts"
+msgstr "Акаунти"
+
+msgid "Authentications"
+msgstr "Автентифікація"
+
+msgid "Automation"
+msgstr "Автоматизація"
+
+msgid "Clients"
+msgstr "Клієнти"
+
+msgid "Collaboration"
+msgstr "Співробітництво"
+
+msgid "Components"
+msgstr "Компоненти"
+
+msgid "Rooms"
+msgstr "Кімнати"
+
+msgid "Directories"
+msgstr "Директорії"
+
+msgid "Gateways"
+msgstr "Маршрутизатори"
+
+msgid "News"
+msgstr "Новини"
+
+msgid "Hierarchy"
+msgstr "Ієрархія"
+
+msgid "Proxies"
+msgstr "Проксі"
+
+msgid "Publication/Subscription"
+msgstr "Публікація / Підписка"
+
+msgid "Storage"
+msgstr ""
+
+msgid "Service offline or broken"
+msgstr "Сервіс не в мережі або зламаний"
+
+msgid "Your inbox"
+msgstr "Вхідні"
+
+msgid "Available actions"
+msgstr "Доступні дії"
+
+msgid "Clean"
+msgstr "Очистити"
+
+msgid "New"
+msgstr "Нові"
+
+msgid "Received"
+msgstr "Отримані"
+
+msgid "Subject"
+msgstr "Тема"
+
+msgid "Content"
+msgstr "Вміст"
+
+msgid "Send message"
+msgstr "Надіслати повідомлення"
+
+msgid "Your inbox is empty."
+msgstr "Немає нових повідомлень"
+
+msgid "MUC administration"
+msgstr ""
+
+msgid "You administrate this room"
+msgstr "Ви адмініструєте цю кімнату"
+
+msgid "Enter new subject"
+msgstr "Введіть нову тему"
+
+msgid "Configuration"
+msgstr "Налаштування"
+
+msgid "Authorizations"
+msgstr "Авторизація"
+
+msgid "Member list"
+msgstr "Список користувачів"
+
+msgid "Owner list"
+msgstr "Список власників"
+
+msgid "Administrator list"
+msgstr "Список адміністраторів"
+
+msgid "Outcast list"
+msgstr ""
+
+msgid "Add an input"
+msgstr ""
+
+msgid "Destroy this MUC"
+msgstr "Знищити конференцію"
+
+msgid "Yes, let's do it!"
+msgstr "Так!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "Ваш друг звернув увагу на бесіду."
+
+msgid "Your friend is writing a message..."
+msgstr "Ваш друг пише повідомлення..."
+
+msgid "Your friend stopped writing a message."
+msgstr "Ваш друг припинив писати повідомлення."
+
+msgid "Your friend is doing something else."
+msgstr "Ваш друг робить щось інше."
+
+msgid "Your friend closed the chat."
+msgstr "Ваш друг закрив чат."
+
+msgid "Requesting this service..."
+msgstr "Запит сервісу..."
+
+msgid "Loading"
+msgstr "Завантаження"
+
+msgid "joined the chat room"
+msgstr "увійшов до кімнати"
+
+msgid "left the chat room"
+msgstr "вийшов з кімнати"
+
+msgid "no status"
+msgstr "нема статусу"
+
+msgid "has been kicked"
+msgstr "було виграно"
+
+msgid "has been banned"
+msgstr "було забанено"
+
+msgid "no reason"
+msgstr "нема причини"
+
+msgid "Communicate with the entire world!"
+msgstr ""
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr ""
+
+msgid "Hi there!"
+msgstr "Привіт!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr ""
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr ""
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr ""
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr ""
+
+msgid "Previous"
+msgstr "Попередній"
+
+msgid "General"
+msgstr "Основні"
+
+msgid "Advanced"
+msgstr "Розширені"
+
+msgid "Resource"
+msgstr "Ресурс"
+
+msgid "Priority"
+msgstr "Приорітет"
+
+msgid "Low"
+msgstr "Низький"
+
+msgid "Medium"
+msgstr "Середній"
+
+msgid "High"
+msgstr "Високий"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr ""
+
+msgid "login page"
+msgstr "Сторінка входу"
+
+msgid "Share this link with your friends:"
+msgstr "Поділитись цим посиланням з другом."
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr ""
+
+msgid "Required"
+msgstr "Потребує"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr ""
+
+msgid "Manager"
+msgstr "Керівник"
+
+msgid "Project"
+msgstr "Проект"
+
+msgid "Encrypted"
+msgstr "Зашифровано"
+
+msgid "Unencrypted"
+msgstr ""
+
+msgid "Where are you?"
+msgstr "Де ти?"
+
+msgid "What's up with you?"
+msgstr "Що з тобою?"
+
+msgid "Fetching the social channel..."
+msgstr "Отримання соціального каналу..."
+
+msgid "You are synchronized with your network."
+msgstr "Ви синхронізовані з вашою мережею."
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "Не можна нічого відправити: ви можете тільки приймати повідомлення!"
+
+msgid "Media viewer"
+msgstr ""
+
+msgid "Browse"
+msgstr "Браузер"
+
+msgid "Command"
+msgstr "Команди"
+
+msgid "Subscribe"
+msgstr "Підписка"
+
+msgid "Join"
+msgstr "Приєднатись"
+
+msgid "Automatic"
+msgstr "Автоматично"
+
+msgid "Search"
+msgstr "Пошук"
+
+msgid "No result!"
+msgstr "Нема результатів!"
+
+msgid "No notifications."
+msgstr "Нема нагадувань."
+
+msgid "would like to add you as a friend."
+msgstr "хоче додати вас як друга."
+
+msgid "would like you to join this chatroom:"
+msgstr "Хоче приєднатись до кімнати:"
+
+msgid "Do you accept?"
+msgstr "Ви приймаєте?"
+
+msgid "Yes"
+msgstr "Так"
+
+msgid "No"
+msgstr "Ні"
+
+msgid "would like to get authorization."
+msgstr "хоче отримати авторизацію."
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr ""
+
+msgid "Submit"
+msgstr "Надіслати"
+
+msgid "Client"
+msgstr "Клієнт"
+
+msgid "System"
+msgstr "Система"
+
+msgid "Local time"
+msgstr "Локальний час"
+
+msgid "Comments"
+msgstr "Коментарі"
+
+msgid "User profile"
+msgstr "Профіль користувача"
+
+msgid "See his/her position on the globe"
+msgstr "Бачити його/її місцезнаходження"
+
+msgid "Confirm"
+msgstr "Підтвердити"
+
+msgid "anonymous mode"
+msgstr "анонімний режим"
+
+msgid "Groups"
+msgstr "Групи"
+
+msgid "Unclassified"
+msgstr "Немає групи"
+
+msgid "Authorize"
+msgstr "Авторизований"
+
+msgid "Ask for authorization"
+msgstr "Надіслати запит авторизації"
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Prohibit"
+msgstr "Заборонити"
+
+msgid "Block"
+msgstr "Заблокувати"
+
+msgid "Chat"
+msgstr "Бесіда"
+
+msgid "Groupchat"
+msgstr "Конференція"
+
+msgid "Jappix Mobile"
+msgstr "мобільний Jappix "
+
+msgid "Desktop"
+msgstr "Повна версія"
+
+msgid "Mobile"
+msgstr "Мобільний"
+
+msgid "Please wait..."
+msgstr "Будь ласка, зачекайте..."
+
+msgid "Please enable JavaScript"
+msgstr "Будь ласка, дозвольте виконання JavaScript"
+
+msgid "Your channel"
+msgstr "Ваш канал"
+
+msgid "Channel of"
+msgstr ""
+
+msgid "More notices..."
+msgstr ""
+
+msgid "Attach a file"
+msgstr "Приєднати файл"
+
+msgid "Send"
+msgstr "Надіслати"
+
+msgid "Unattach the file"
+msgstr "Видалити файл"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr ""
+
+msgid "Authorization failed"
+msgstr "Помилка авторизації"
+
+msgid "Registration failed, please choose a different username"
+msgstr ""
+
+msgid "Service unavailable"
+msgstr "Сервіс недоступний"
+
+msgid "Internal server error, try later"
+msgstr ""
+
+msgid "Your form has been sent."
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "XMPP links"
+msgstr ""
+
+msgid "Open XMPP links with Jappix"
+msgstr ""
+
+msgid "changed the subject to:"
+msgstr ""
+
+msgid "Welcome!"
+msgstr ""
+
+msgid "Friends"
+msgstr "Друзі"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr ""
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr ""
+
+msgid "Enable notification sounds"
+msgstr ""
+
+msgid "Share your position on the globe"
+msgstr ""
+
+msgid "Offline friends"
+msgstr ""
+
+msgid "Don't hide offline friends"
+msgstr ""
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr ""
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr ""
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr ""
+
+msgid "Unknown name"
+msgstr ""
+
+msgid "Unknown country"
+msgstr ""
+
+msgid "Click to enable"
+msgstr ""
+
+msgid "Click to disable"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Jappix installation"
+msgstr ""
+
+msgid "Welcome to the Jappix installation!"
+msgstr ""
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr ""
+
+msgid "Let's have a look at the installation steps:"
+msgstr ""
+
+msgid "Welcome"
+msgstr ""
+
+msgid "Storage configuration"
+msgstr ""
+
+msgid "Administrator account"
+msgstr ""
+
+msgid "Main configuration"
+msgstr ""
+
+msgid "Hosts configuration"
+msgstr ""
+
+msgid "Services installation"
+msgstr ""
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr ""
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr ""
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr ""
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr ""
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr ""
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service name"
+msgstr ""
+
+msgid "Service description"
+msgstr ""
+
+msgid "Connection"
+msgstr ""
+
+msgid "Lock the host"
+msgstr ""
+
+msgid "Anonymous mode"
+msgstr ""
+
+msgid "Registration allowed"
+msgstr ""
+
+msgid "Use a proxy"
+msgstr ""
+
+msgid "Encryption"
+msgstr ""
+
+msgid "HTTPS storage"
+msgstr ""
+
+msgid "Force HTTPS"
+msgstr ""
+
+msgid "Compression"
+msgstr ""
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr ""
+
+msgid "Groupchat host"
+msgstr ""
+
+msgid "Anonymous host"
+msgstr ""
+
+msgid "Directory host"
+msgstr ""
+
+msgid "BOSH host"
+msgstr ""
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr ""
+
+msgid "Thanks for using Jappix!"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Finish"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr ""
+
+msgid "%s is installed on your system."
+msgstr ""
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr ""
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr ""
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr ""
+
+msgid "Jappix manager"
+msgstr ""
+
+msgid "Manager access"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Hosts"
+msgstr ""
+
+msgid "Design"
+msgstr ""
+
+msgid "Repeat"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Horizontal"
+msgstr ""
+
+msgid "Vertical"
+msgstr ""
+
+msgid "Center"
+msgstr ""
+
+msgid "Left"
+msgstr ""
+
+msgid "Right"
+msgstr ""
+
+msgid "Top"
+msgstr ""
+
+msgid "Bottom"
+msgstr ""
+
+msgid "Adapt"
+msgstr ""
+
+msgid "Color"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr ""
+
+msgid "Please use the form below to login to the administration panel."
+msgstr ""
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "You have been logged out. Goodbye!"
+msgstr ""
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr ""
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr ""
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr ""
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr ""
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr ""
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr ""
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr ""
+
+msgid "The image could not be received, would you mind retry?"
+msgstr ""
+
+msgid "Your image was added to the list!"
+msgstr ""
+
+msgid "Changes saved!"
+msgstr ""
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr ""
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr ""
+
+msgid "Access statistics"
+msgstr ""
+
+msgid "Share statistics"
+msgstr ""
+
+msgid "Other statistics"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Cache"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Music"
+msgstr ""
+
+msgid "Backgrounds"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Background"
+msgstr ""
+
+msgid "Notice"
+msgstr ""
+
+msgid "Your design preferences have been saved!"
+msgstr ""
+
+msgid "Please check your inputs: something is missing!"
+msgstr ""
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr ""
+
+msgid "Use default background"
+msgstr ""
+
+msgid "Use your own image"
+msgstr ""
+
+msgid "Select a background to use and change the display options."
+msgstr ""
+
+msgid "Use your own color"
+msgstr ""
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr ""
+
+msgid "Manage backgrounds"
+msgstr ""
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr ""
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr ""
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr ""
+
+msgid "What's new?"
+msgstr ""
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr ""
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr ""
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr ""
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr ""
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr ""
+
+msgid "Check for updates"
+msgstr ""
+
+msgid "Update in progress"
+msgstr ""
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr ""
+
+msgid "The update has failed! Please try again later."
+msgstr ""
+
+msgid "Downloading package..."
+msgstr ""
+
+msgid "Removing current Jappix system files..."
+msgstr ""
+
+msgid "Extracting package..."
+msgstr ""
+
+msgid "Regenerating storage folder tree..."
+msgstr ""
+
+msgid "Jappix is now up to date!"
+msgstr ""
+
+msgid "Aborted: socket error!"
+msgstr ""
+
+msgid "Aborted: buffer error!"
+msgstr ""
+
+msgid "Aborted: everything is not writable!"
+msgstr ""
+
+msgid "Aborted: could not extract the package!"
+msgstr ""
+
+msgid "Visits"
+msgstr ""
+
+msgid "Daily"
+msgstr ""
+
+msgid "Weekly"
+msgstr ""
+
+msgid "Monthly"
+msgstr ""
+
+msgid "Yearly"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Clean everything"
+msgstr ""
+
+msgid "Purge cache"
+msgstr ""
+
+msgid "Purge logs"
+msgstr ""
+
+msgid "Purge updates"
+msgstr ""
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr ""
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr ""
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr ""
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr ""
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Artist"
+msgstr ""
+
+msgid "Album"
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "Upload"
+msgstr ""
+
+msgid "The folder is empty."
+msgstr ""
+
+msgid "The music could not be received, please retry!"
+msgstr ""
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr ""
+
+msgid "Your music has been added!"
+msgstr ""
+
+msgid "The selected elements have been removed."
+msgstr ""
+
+msgid "You must select elements to remove!"
+msgstr ""
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr ""
+
+msgid "The user has been added!"
+msgstr ""
+
+msgid "The chosen users have been removed."
+msgstr ""
+
+msgid "You must select one or more users to be removed!"
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "%s days ago"
+msgstr ""
+
+msgid "User currently active"
+msgstr ""
+
+msgid "Last seen: %s"
+msgstr ""
+
+msgid "Inactive since: %s"
+msgstr ""
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr ""
+
+msgid "Static content server"
+msgstr ""
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr ""
+
+msgid "Suggested friends"
+msgstr ""
+
+msgid "Check all"
+msgstr ""
+
+msgid "Uncheck all"
+msgstr ""
+
+msgid "Choose"
+msgstr ""
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr ""
+
+msgid "Send messages"
+msgstr ""
+
+msgid "Send queries"
+msgstr ""
+
+msgid "See my status"
+msgstr ""
+
+msgid "Send his/her status"
+msgstr ""
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr ""
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr ""
+
+msgid "Search a friend"
+msgstr ""
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr ""
+
+msgid "Type your comment here..."
+msgstr ""
+
+msgid "Could not get the comments!"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Send him/her a message"
+msgstr ""
+
+msgid "Start a chat with him/her"
+msgstr ""
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/lang/zh/LC_MESSAGES/main.mo b/jappixmini/jappix/lang/zh/LC_MESSAGES/main.mo
new file mode 100644 (file)
index 0000000..f730fbf
Binary files /dev/null and b/jappixmini/jappix/lang/zh/LC_MESSAGES/main.mo differ
diff --git a/jappixmini/jappix/lang/zh/LC_MESSAGES/main.po b/jappixmini/jappix/lang/zh/LC_MESSAGES/main.po
new file mode 100644 (file)
index 0000000..6ae0449
--- /dev/null
@@ -0,0 +1,1870 @@
+# Chinese translations for Jappix package.
+# This file is distributed under the same license as the Jappix package.
+# This file was translated from CodingTeam at <http://codingteam.net/>.
+msgid ""
+msgstr ""
+"Project-Id-Version: Jappix\n"
+"PO-Revision-Date: 2012-01-16 21:26+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"POT-Creation-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+
+msgid "JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."
+msgstr "在你的網頁瀏覽器找不到 JavaScript,所以你無法啟動 Jappix!請修正。"
+
+msgid "An open social network"
+msgstr "開放社交網路"
+
+msgid "Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience."
+msgstr "Jappix 已經因為網路問題、bug 或登入錯誤(檢查你輸入了正確的身份證明)而被中斷,抱歉造成不便。"
+
+msgid "The element list on this server could not be obtained!"
+msgstr "此伺服器的元素清單無法取得!"
+
+msgid "Your password has been changed, now you can connect to your account with your new login data."
+msgstr "你的密碼已被變更,現在你可以用新的登入資料連到你的帳號。"
+
+msgid "Your XMPP account has been removed, bye!"
+msgstr "你的 XMPP 帳號已被刪除,再見!"
+
+msgid "You have been logged out of your XMPP account, have a nice day!"
+msgstr "你已經登出你的 XMPP 帳號,祝你今天愉快!"
+
+msgid "The room you joined seems not to exist. You should create it!"
+msgstr "你加入的房間似乎不存在。你應該建立它!"
+
+msgid "The groupchat has been removed, now someone else will be able to recreate it."
+msgstr "群組聊天已經被刪除,現在其他人應該可以重新建立它。"
+
+msgid "The user that you want to reach is not present in the room."
+msgstr "你想聯繫的使用者不在房間內。"
+
+msgid "Please enter the group chat address to join."
+msgstr "請輸入要加入的群組聊天地址。"
+
+msgid "Please enter your nickname to join %s."
+msgstr "請輸入要加入 %s 用的暱稱。"
+
+msgid "This room (%s) is protected with a password."
+msgstr "此房間(%s)有密碼保護。"
+
+msgid "Your browser is out of date!"
+msgstr "你的瀏覽器已經過時!"
+
+msgid "Last %s version is better!"
+msgstr "推鑒使用最新版本 %s!"
+
+msgid "Login"
+msgstr "登入"
+
+msgid "Register"
+msgstr "註冊"
+
+msgid "Here we go!"
+msgstr "開始囉!"
+
+msgid "Server"
+msgstr "伺服器"
+
+msgid "Password"
+msgstr "密碼"
+
+msgid "Remember me"
+msgstr "記住我"
+
+msgid "This tool has been disabled, you cannot use it!"
+msgstr "此工具已被停用,你不能使用它!"
+
+msgid "Due to a network issue, you were disconnected. What do you want to do now?"
+msgstr "因為網路問題,你已被斷線。你現在想做什麼?"
+
+msgid "Reconnect"
+msgstr "重新連線"
+
+msgid "Messages"
+msgstr "訊息"
+
+msgid "Profile"
+msgstr "個人資料"
+
+msgid "Options"
+msgstr "選項"
+
+msgid "Disconnect"
+msgstr "斷線"
+
+msgid "Filter"
+msgstr "過濾"
+
+msgid "Add a friend"
+msgstr "新增好友"
+
+msgid "Your groupchats"
+msgstr "你的群組聊天"
+
+msgid "Manage your favorite groupchats"
+msgstr "管理你最愛的群組聊天"
+
+msgid "More stuff"
+msgstr "更多東西"
+
+msgid "Show all friends"
+msgstr "顯示所有好友"
+
+msgid "Only show connected friends"
+msgstr "只顯示已連線的好友"
+
+msgid "Message archives"
+msgstr "訊息存檔"
+
+msgid "Date"
+msgstr "日期"
+
+msgid "Please select a friend to view the chat history."
+msgstr "請選取要檢視聊天記錄的朋友。"
+
+msgid "Nothing found for: %s"
+msgstr "找不到:%s"
+
+msgid "A short message?"
+msgstr "短訊息?"
+
+msgid "How are you?"
+msgstr "你好嗎?"
+
+msgid "What are you doing?"
+msgstr "你在做什麼?"
+
+msgid "Join a chat"
+msgstr "加入聊天"
+
+msgid "Status"
+msgstr "狀態"
+
+msgid "Available"
+msgstr "有空"
+
+msgid "Talkative"
+msgstr "多話"
+
+msgid "Away"
+msgstr "離開"
+
+msgid "Not available"
+msgstr "沒空"
+
+msgid "Busy"
+msgstr "忙碌"
+
+msgid "Mood"
+msgstr "心情"
+
+msgid "None"
+msgstr "無"
+
+msgid "Crazy"
+msgstr "抓狂"
+
+msgid "Excited"
+msgstr "興奮"
+
+msgid "Playful"
+msgstr "快活"
+
+msgid "Happy"
+msgstr "快樂"
+
+msgid "Shocked"
+msgstr "震驚"
+
+msgid "Hot"
+msgstr "激動"
+
+msgid "Sad"
+msgstr "悲傷"
+
+msgid "Amorous"
+msgstr "愛慕"
+
+msgid "Confident"
+msgstr "大膽"
+
+msgid "Activity"
+msgstr "活動"
+
+msgid "Chores"
+msgstr "雜事"
+
+msgid "Drinking"
+msgstr "喝"
+
+msgid "Eating"
+msgstr "吃"
+
+msgid "Exercising"
+msgstr "運動"
+
+msgid "Grooming"
+msgstr "訓練"
+
+msgid "Appointment"
+msgstr "預約"
+
+msgid "Inactive"
+msgstr "無效"
+
+msgid "Relaxing"
+msgstr "放鬆"
+
+msgid "Talking"
+msgstr "對話"
+
+msgid "Traveling"
+msgstr "旅行"
+
+msgid "Working"
+msgstr "工作"
+
+msgid "View profile"
+msgstr "檢視個人資料"
+
+msgid "Repeat this notice"
+msgstr "重覆此通知"
+
+msgid "Remove this notice"
+msgstr "刪除此通知"
+
+msgid "Your profile"
+msgstr "你的個人資料"
+
+msgid "Identity"
+msgstr "身分證明"
+
+msgid "Profile image"
+msgstr "大頭貼"
+
+msgid "Others"
+msgstr "其他"
+
+msgid "Personal"
+msgstr "個人"
+
+msgid "Complete name"
+msgstr "全名"
+
+msgid "Nickname"
+msgstr "暱稱"
+
+msgid "First name"
+msgstr "名"
+
+msgid "Last name"
+msgstr "姓"
+
+msgid "Date of birth"
+msgstr "生日"
+
+msgid "Contact"
+msgstr "連絡人"
+
+msgid "E-mail"
+msgstr "電子郵件"
+
+msgid "Phone"
+msgstr "電話"
+
+msgid "Website"
+msgstr "網站"
+
+msgid "Current"
+msgstr "目前"
+
+msgid "Delete"
+msgstr "刪除"
+
+msgid "What a pity! You have no profile image defined in your identity card!"
+msgstr "可惜!你沒有在你的身份證上設定大頭貼!"
+
+msgid "Address"
+msgstr "地址"
+
+msgid "Street"
+msgstr "街"
+
+msgid "City"
+msgstr "市"
+
+msgid "Postal code"
+msgstr "郵遞區號"
+
+msgid "Country"
+msgstr "國家"
+
+msgid "Biography"
+msgstr "自傳"
+
+msgid "Important notice"
+msgstr "重要通知"
+
+msgid "Be careful of the information you write into your profile, because it could be accessed by everyone (even someone you don't want to)."
+msgstr "小心你寫入個人資料的資訊,因為它可被每個人取得(甚至你不要的人)。"
+
+msgid "Not everything is private on XMPP; this is one of those things, your public profile (vCard)."
+msgstr "在 XMPP 上不是每樣東西是私有的;這是其中一件,你的公開個人資料(vCard)。"
+
+msgid "It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."
+msgstr "強烈建議上傳大頭照(最大 %s),像是你自己的相片,因為那會使你的朋友更容易認得你。"
+
+msgid "Save"
+msgstr "儲存"
+
+msgid "Cancel"
+msgstr "取消"
+
+msgid "Edit options"
+msgstr "編輯選項"
+
+msgid "Channel"
+msgstr "頻道"
+
+msgid "Commands"
+msgstr "命令"
+
+msgid "Sounds"
+msgstr "聲音"
+
+msgid "Privacy"
+msgstr "隱私"
+
+msgid "Message archiving"
+msgstr "訊息存檔"
+
+msgid "Store a history of your chats"
+msgstr "儲存你的聊天記錄"
+
+msgid "Geolocation"
+msgstr "地理位置"
+
+msgid "Empty"
+msgstr "空"
+
+msgid "Empty channel"
+msgstr "空的頻道"
+
+msgid "Persistent"
+msgstr "持續"
+
+msgid "Maximum notices"
+msgstr "通知的最大數"
+
+msgid "Account"
+msgstr "帳號"
+
+msgid "Change password"
+msgstr "變更密碼"
+
+msgid "Delete account"
+msgstr "刪除帳號"
+
+msgid "Old"
+msgstr "舊"
+
+msgid "New (2 times)"
+msgstr "新(2 次)"
+
+msgid "Continue"
+msgstr "繼續"
+
+msgid "To"
+msgstr "至"
+
+msgid "Close"
+msgstr "關閉"
+
+msgid "unknown"
+msgstr "不明"
+
+msgid "Unavailable"
+msgstr "無法使用"
+
+msgid "is now"
+msgstr "現在是"
+
+msgid "Please wait while your avatar is uploaded..."
+msgstr "請稍待,avatar 正被載入..."
+
+msgid "Here it is! A new beautiful profile image!"
+msgstr "在此!美麗的新大頭貼!"
+
+msgid "The image file is not supported or has a bad size."
+msgstr "影像檔不被支援或大小錯誤。"
+
+msgid "Reply"
+msgstr "回覆"
+
+msgid "Error"
+msgstr "錯誤"
+
+msgid "Click here to solve the error"
+msgstr "在此點一下以解決錯誤"
+
+msgid "You"
+msgstr "你"
+
+msgid "Remove"
+msgstr "刪除"
+
+msgid "Rename"
+msgstr "更名"
+
+msgid "Hi, I am %s, I would like to add you as my friend."
+msgstr "嗨,我是 %s,我想把你加入為我的好友。"
+
+msgid "Smiley insertion"
+msgstr "挿入微笑符號"
+
+msgid "Change style"
+msgstr "變更風格"
+
+msgid "Text in bold"
+msgstr "粗體字"
+
+msgid "Text in italic"
+msgstr "斜體字"
+
+msgid "Underlined text"
+msgstr "底線字"
+
+msgid "Save chat"
+msgstr "儲存聊天"
+
+msgid "Click on the following link to get the chat log, and wait. Then click again to get the file."
+msgstr "在以下連結點一下以取得聊天記錄,且稍待。然後再點一下取得檔案。"
+
+msgid "This chat is empty!"
+msgstr "此聊天是空的!"
+
+msgid "Generate file!"
+msgstr "產生檔案!"
+
+msgid "Download file!"
+msgstr "下載檔案!"
+
+msgid "Clean current chat"
+msgstr "清除目前的聊天"
+
+msgid "View chat history"
+msgstr "檢視聊天記錄"
+
+msgid "Show user profile"
+msgstr "顯示使用者個人資料"
+
+msgid "Add this contact to your friends"
+msgstr "加入此連絡人至你的好友"
+
+msgid "Add this groupchat to your favorites"
+msgstr "加入此群組聊天至你的最愛"
+
+msgid "All tabs"
+msgstr "全部頁籤"
+
+msgid "Close this tab"
+msgstr "關閉此頁籤"
+
+msgid "no subject defined for this room."
+msgstr "此房間未設定主旨。"
+
+msgid "Administration panel for this room"
+msgstr "此房間的管理面板"
+
+msgid "Moderators"
+msgstr "主持人"
+
+msgid "Participants"
+msgstr "参與者"
+
+msgid "Visitors"
+msgstr "訪客"
+
+msgid "Manage favorite rooms"
+msgstr "管理最愛的房間"
+
+msgid "Change favorites"
+msgstr "變更我的最愛"
+
+msgid "Search a room"
+msgstr "搜尋房間"
+
+msgid "Select a favorite"
+msgstr "選取我的最愛"
+
+msgid "Getting the name..."
+msgstr "正在取得名稱..."
+
+msgid "Gateway"
+msgstr "閘道"
+
+msgid "Name"
+msgstr "名稱"
+
+msgid "Room"
+msgstr "房間"
+
+msgid "Add"
+msgstr "增加"
+
+msgid "Edit"
+msgstr "編輯"
+
+msgid "Search a room on"
+msgstr "搜尋房間於"
+
+msgid "No room found on this server."
+msgstr "在此伺服器上找不到房間。"
+
+msgid "Service discovery"
+msgstr "服務探索"
+
+msgid "Server to query"
+msgstr "查詢的伺服器"
+
+msgid "Sorry, but the entity didn't return any result!"
+msgstr "抱歉,但是那實體未傳回任何結果!"
+
+msgid "Accounts"
+msgstr "帳號"
+
+msgid "Authentications"
+msgstr "授權"
+
+msgid "Automation"
+msgstr "自動"
+
+msgid "Clients"
+msgstr "客戶端"
+
+msgid "Collaboration"
+msgstr "協同"
+
+msgid "Components"
+msgstr "元件"
+
+msgid "Rooms"
+msgstr "房間"
+
+msgid "Directories"
+msgstr "目錄"
+
+msgid "Gateways"
+msgstr "閘道"
+
+msgid "News"
+msgstr "新聞"
+
+msgid "Hierarchy"
+msgstr "階層"
+
+msgid "Proxies"
+msgstr "代理伺服器"
+
+msgid "Publication/Subscription"
+msgstr "公開/訂閱"
+
+msgid "Storage"
+msgstr "儲存空間"
+
+msgid "Service offline or broken"
+msgstr "服務離線或故障"
+
+msgid "Your inbox"
+msgstr "你的收件匣"
+
+msgid "Available actions"
+msgstr "可用的動作"
+
+msgid "Clean"
+msgstr "清除"
+
+msgid "New"
+msgstr "新增"
+
+msgid "Received"
+msgstr "已接收"
+
+msgid "Subject"
+msgstr "主旨"
+
+msgid "Content"
+msgstr "内容"
+
+msgid "Send message"
+msgstr "傳送訊息"
+
+msgid "Your inbox is empty."
+msgstr "你的收件匣是空的。"
+
+msgid "MUC administration"
+msgstr "MUC 管理"
+
+msgid "You administrate this room"
+msgstr "你管理此房間"
+
+msgid "Enter new subject"
+msgstr "輸入新的主旨"
+
+msgid "Configuration"
+msgstr "設定"
+
+msgid "Authorizations"
+msgstr "授權"
+
+msgid "Member list"
+msgstr "會員清單"
+
+msgid "Owner list"
+msgstr "所有者清單"
+
+msgid "Administrator list"
+msgstr "管理員清單"
+
+msgid "Outcast list"
+msgstr "被放逐者清單"
+
+msgid "Add an input"
+msgstr "增加輸入"
+
+msgid "Destroy this MUC"
+msgstr "銷毀此 MUC"
+
+msgid "Yes, let's do it!"
+msgstr "是,做吧!"
+
+msgid "Your friend is paying attention to the conversation."
+msgstr "你的好友正在注意會話。"
+
+msgid "Your friend is writing a message..."
+msgstr "你的好友正在寫訊息..."
+
+msgid "Your friend stopped writing a message."
+msgstr "你的好友停止寫訊息。"
+
+msgid "Your friend is doing something else."
+msgstr "你的好友正在做其他事。"
+
+msgid "Your friend closed the chat."
+msgstr "你的好友關閉了聊天。"
+
+msgid "Requesting this service..."
+msgstr "正在要求此服務..."
+
+msgid "Loading"
+msgstr "載入中"
+
+msgid "joined the chat room"
+msgstr "加入聊天室"
+
+msgid "left the chat room"
+msgstr "離開聊天室"
+
+msgid "no status"
+msgstr "無狀態"
+
+msgid "has been kicked"
+msgstr "已被踢掉"
+
+msgid "has been banned"
+msgstr "已被禁止"
+
+msgid "no reason"
+msgstr "無理由"
+
+msgid "Communicate with the entire world!"
+msgstr "與全世界溝通!"
+
+msgid "It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"
+msgstr "它允許你與幾百萬跟你一樣正在利用 Jappix 的使用者聯繫。自由地加入社群吧!"
+
+msgid "Hi there!"
+msgstr "你好!"
+
+msgid "Welcome on %1s, “%2s”."
+msgstr "歡迎來到 %1s,“%2s”。"
+
+msgid "Login to your existing XMPP account or create a new one for free!"
+msgstr "登入你已有的 XMPP 帳號或免費建立新帳號!"
+
+msgid "Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help."
+msgstr "Jappix 是來自 PostPro 的開放原始碼專案,一個提供我們許多幫助的非營利團體。"
+
+msgid "Login to your existing XMPP account. You can also use the %s to join a groupchat."
+msgstr "登入你已有的 XMPP 帳號。你也可以使用 %s 加入群組聊天。"
+
+msgid "Previous"
+msgstr "上一頁"
+
+msgid "General"
+msgstr "一般"
+
+msgid "Advanced"
+msgstr "進階"
+
+msgid "Resource"
+msgstr "資源"
+
+msgid "Priority"
+msgstr "優先權"
+
+msgid "Low"
+msgstr "低"
+
+msgid "Medium"
+msgstr "中"
+
+msgid "High"
+msgstr "高"
+
+msgid "Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."
+msgstr "輸入你想加入的聊天群組與你想要的暱稱。你也可以回到 %s。"
+
+msgid "login page"
+msgstr "登入頁"
+
+msgid "Share this link with your friends:"
+msgstr "與好友分享此連結:"
+
+msgid "Register a new XMPP account to join your friends on your own social cloud. That's simple!"
+msgstr "註冊一個新的 XMPP 帳號以便在你自己的社交雲端上加入你的好友。那是簡單的!"
+
+msgid "Required"
+msgstr "要求"
+
+msgid "You have been registered, here is your XMPP address:"
+msgstr "你已經註冊了,這是你的 XMPP 地址:"
+
+msgid "Manager"
+msgstr "管理員"
+
+msgid "Project"
+msgstr "專案"
+
+msgid "Encrypted"
+msgstr "加密"
+
+msgid "Unencrypted"
+msgstr "未加密"
+
+msgid "Where are you?"
+msgstr "你在哪裡?"
+
+msgid "What's up with you?"
+msgstr "你怎麼了?"
+
+msgid "Fetching the social channel..."
+msgstr "取得社交頻道..."
+
+msgid "You are synchronized with your network."
+msgstr "你已與你的網路同步。"
+
+msgid "Cannot send anything: you can only receive notices!"
+msgstr "無法傳送任何東西:你只能接收通知!"
+
+msgid "Media viewer"
+msgstr "媒體播放機"
+
+msgid "Browse"
+msgstr "瀏覽"
+
+msgid "Command"
+msgstr "命令"
+
+msgid "Subscribe"
+msgstr "訂閱"
+
+msgid "Join"
+msgstr "加入"
+
+msgid "Automatic"
+msgstr "自動"
+
+msgid "Search"
+msgstr "搜尋"
+
+msgid "No result!"
+msgstr "無結果!"
+
+msgid "No notifications."
+msgstr "無通知。"
+
+msgid "would like to add you as a friend."
+msgstr "想要加入你為好友。"
+
+msgid "would like you to join this chatroom:"
+msgstr "想要你加入此聊天室:"
+
+msgid "Do you accept?"
+msgstr "你接受嗎?"
+
+msgid "Yes"
+msgstr "是"
+
+msgid "No"
+msgstr "否"
+
+msgid "would like to get authorization."
+msgstr "想要得到授權。"
+
+msgid "Do you want to see the friends %s suggests you?"
+msgstr "你要看好友 %s 建議你?"
+
+msgid "Submit"
+msgstr "送信"
+
+msgid "Client"
+msgstr "客戶端"
+
+msgid "System"
+msgstr "系統"
+
+msgid "Local time"
+msgstr "本地時間"
+
+msgid "Comments"
+msgstr "評論"
+
+msgid "User profile"
+msgstr "使用者情報"
+
+msgid "See his/her position on the globe"
+msgstr "看他在地球上的位置"
+
+msgid "Confirm"
+msgstr "確認"
+
+msgid "anonymous mode"
+msgstr "匿名模式"
+
+msgid "Groups"
+msgstr "群組"
+
+msgid "Unclassified"
+msgstr "未分類"
+
+msgid "Authorize"
+msgstr "授權"
+
+msgid "Ask for authorization"
+msgstr "要求授權"
+
+msgid "Unblock"
+msgstr "解除鎖定"
+
+msgid "Prohibit"
+msgstr "禁止"
+
+msgid "Block"
+msgstr "阻擋"
+
+msgid "Chat"
+msgstr "聊天"
+
+msgid "Groupchat"
+msgstr "群組聊天"
+
+msgid "Jappix Mobile"
+msgstr "Jappix 行動"
+
+msgid "Desktop"
+msgstr "桌面"
+
+msgid "Mobile"
+msgstr "行動"
+
+msgid "Please wait..."
+msgstr "請稍待..."
+
+msgid "Please enable JavaScript"
+msgstr "請啟用 JavaScript"
+
+msgid "Your channel"
+msgstr "你的頻道"
+
+msgid "Channel of"
+msgstr "頻道: "
+
+msgid "More notices..."
+msgstr "更多通知..."
+
+msgid "Attach a file"
+msgstr "附加檔案"
+
+msgid "Send"
+msgstr "傳送"
+
+msgid "Unattach the file"
+msgstr "取消附加檔案"
+
+msgid "An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"
+msgstr "當上傳你的檔案時發生錯誤:也許它太大(最大 %s)或被禁止!"
+
+msgid "Authorization failed"
+msgstr "授權失敗"
+
+msgid "Registration failed, please choose a different username"
+msgstr "註冊失敗,請挑選另一個使用者名稱"
+
+msgid "Service unavailable"
+msgstr "服務無法使用"
+
+msgid "Internal server error, try later"
+msgstr "内部伺服器錯誤,稍後再試"
+
+msgid "Your form has been sent."
+msgstr "你的表單已被送出。"
+
+msgid "Application"
+msgstr "應用程式"
+
+msgid "XMPP links"
+msgstr "XMPP 連結"
+
+msgid "Open XMPP links with Jappix"
+msgstr "用 Jappix 開啟 XMPP 連結"
+
+msgid "changed the subject to:"
+msgstr "變更主旨為:"
+
+msgid "Welcome!"
+msgstr "歡迎!"
+
+msgid "Friends"
+msgstr "好友"
+
+msgid "Welcome on Jappix, your own social cloud!"
+msgstr "歡迎來到 Jappix,你自己的社交雲端!"
+
+msgid "Before you start using it, you will have to change some settings, search for friends and complete your profile."
+msgstr "在你開使使用它之前,你必須變更一些設定,搜尋朋友並完成你的個人資訊。"
+
+msgid "Enable notification sounds"
+msgstr "啟用通知音效"
+
+msgid "Share your position on the globe"
+msgstr "分享你在地球上的位置"
+
+msgid "Offline friends"
+msgstr "離線好友"
+
+msgid "Don't hide offline friends"
+msgstr "不要隱藏離線好友"
+
+msgid "Use this tool to find your friends on the server you are using right now, or add them later."
+msgstr "使用此工具在你正在使用的伺服器上找到你的朋友,或稍後加入他們。"
+
+msgid "Great work! Now, you can share Jappix with your friends!"
+msgstr ""
+
+msgid "When you will press the save button, the profile editor will be opened. Happy socializing!"
+msgstr ""
+
+msgid "Share Jappix on %s"
+msgstr "在 %s 上分享 Jappix"
+
+msgid "Using Jappix, an open social platform. I am %s!"
+msgstr "使用 Jappix,一個開放社交平台。我是 %s!"
+
+msgid "Unknown name"
+msgstr "不明的名稱"
+
+msgid "Unknown country"
+msgstr "不明的國家"
+
+msgid "Click to enable"
+msgstr "點一下以啟用"
+
+msgid "Click to disable"
+msgstr "點一下以停用"
+
+msgid "Installation"
+msgstr "安裝"
+
+msgid "Jappix installation"
+msgstr "Jappix 安裝"
+
+msgid "Welcome to the Jappix installation!"
+msgstr "歡迎來到 Jappix 安裝!"
+
+msgid "This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."
+msgstr "此工具將幫你快速地安裝 Jappix,第一個全功能以 XMPP 為基礎的社交平台。你甚至不需要任何技術知識。"
+
+msgid "Let's have a look at the installation steps:"
+msgstr "讓我們看一下安裝步驟:"
+
+msgid "Welcome"
+msgstr "歡迎"
+
+msgid "Storage configuration"
+msgstr "儲存空間設定"
+
+msgid "Administrator account"
+msgstr "管理員帳號"
+
+msgid "Main configuration"
+msgstr "主要設定"
+
+msgid "Hosts configuration"
+msgstr "主機設定"
+
+msgid "Services installation"
+msgstr "服務安裝"
+
+msgid "If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."
+msgstr "如果目前的語言與你的不符(%1s),你可以讓 Jappix 說 %2s 它將被儲存。"
+
+msgid "If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"
+msgstr ""
+
+msgid "It's time to build your own social cloud: just go to the next step!"
+msgstr ""
+
+msgid "Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."
+msgstr ""
+
+msgid "Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."
+msgstr ""
+
+msgid "The folder is writable, you can continue!"
+msgstr "資料夾可寫入,你可以繼續!"
+
+msgid "Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."
+msgstr ""
+
+msgid "When Jappix will be installed, just click on the manager link on the home page to access it."
+msgstr "當 Jappix 安裝完成後,只要點一下首頁上的管理員連結就可以進入。"
+
+msgid "Oops, you missed something or the two passwords do not match!"
+msgstr "糟糕,你漏了某些東西或兩個密碼不一致!"
+
+msgid "Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."
+msgstr "Jappix 需要你指定某些值才能開始工作。請確認下列輸入(或保留預設值,對大多數人來說是足夠的)。"
+
+msgid "Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."
+msgstr ""
+
+msgid "User"
+msgstr "使用者"
+
+msgid "Service"
+msgstr "服務"
+
+msgid "Service name"
+msgstr "服務名稱"
+
+msgid "Service description"
+msgstr "服務説明"
+
+msgid "Connection"
+msgstr "連線"
+
+msgid "Lock the host"
+msgstr "鎖定主機"
+
+msgid "Anonymous mode"
+msgstr "匿名模式"
+
+msgid "Registration allowed"
+msgstr "允許註冊"
+
+msgid "Use a proxy"
+msgstr "使用代理伺服器"
+
+msgid "Encryption"
+msgstr "加密"
+
+msgid "HTTPS storage"
+msgstr "HTTPS 儲存空間"
+
+msgid "Force HTTPS"
+msgstr "強制使用 HTTPS"
+
+msgid "Compression"
+msgstr "壓縮"
+
+msgid "This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."
+msgstr ""
+
+msgid "Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."
+msgstr ""
+
+msgid "Main host"
+msgstr "主要主機"
+
+msgid "Groupchat host"
+msgstr "群組聊天主機"
+
+msgid "Anonymous host"
+msgstr "匿名主機"
+
+msgid "Directory host"
+msgstr "目錄主機"
+
+msgid "BOSH host"
+msgstr "BOSH 主機"
+
+msgid "You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."
+msgstr ""
+
+msgid "To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."
+msgstr ""
+
+msgid "After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."
+msgstr "在你完成設定後,Jappix 將產生一些快取檔案。它也許會費時,只能等到應用程式顯示且不要按任何按鈕。"
+
+msgid "Thanks for using Jappix!"
+msgstr "感謝使用 Jappix!"
+
+msgid "Next"
+msgstr "下一頁"
+
+msgid "Finish"
+msgstr "完成"
+
+msgid "Check again"
+msgstr "再檢查"
+
+msgid "The folder is not writable, set the right permissions to the %s directory."
+msgstr "資料夾不可寫入,設定正確權限至 %s 目錄。"
+
+msgid "%s is installed on your system."
+msgstr "%s 已經安裝在你的系統。"
+
+msgid "%1s is not installed on your system, you should install %2s."
+msgstr "%1s 未安裝在你的系統,你需要安裝 %2s。"
+
+msgid "PHP maximum upload size is sufficient (%s)."
+msgstr "PHP 最大上傳已足夠(%s)。"
+
+msgid "PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."
+msgstr "PHP 最大上傳不足夠(%1s),你必須定義它為 %2s 在 %3s 中。"
+
+msgid "Jappix manager"
+msgstr "Jappix 管理員"
+
+msgid "Manager access"
+msgstr "管理員入口"
+
+msgid "Statistics"
+msgstr "統計"
+
+msgid "Hosts"
+msgstr "主機"
+
+msgid "Design"
+msgstr "設計"
+
+msgid "Repeat"
+msgstr "報告"
+
+msgid "All"
+msgstr "全部"
+
+msgid "Horizontal"
+msgstr "水平"
+
+msgid "Vertical"
+msgstr "垂直"
+
+msgid "Center"
+msgstr "中"
+
+msgid "Left"
+msgstr "左"
+
+msgid "Right"
+msgstr "右"
+
+msgid "Top"
+msgstr "上"
+
+msgid "Bottom"
+msgstr "下"
+
+msgid "Adapt"
+msgstr "適用"
+
+msgid "Color"
+msgstr "色彩"
+
+msgid "Users"
+msgstr "使用者"
+
+msgid "Updates"
+msgstr "更新"
+
+msgid "This is a restricted area: only the authorized users can manage this Jappix node."
+msgstr "這是限制區域:只有得到授權的使用者可以管理此 Jappix 節點。"
+
+msgid "Please use the form below to login to the administration panel."
+msgstr "請使用下面的表單登入管理面板。"
+
+msgid "To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."
+msgstr ""
+
+msgid "Credentials"
+msgstr "身份證明"
+
+msgid "You have been logged out. Goodbye!"
+msgstr "你已經被登出。再見!"
+
+msgid "Oops, you could not be recognized as a valid administrator. Check your credentials!"
+msgstr "糟糕,你無法被認為是有效的管理員。檢查你的身份證明!"
+
+msgid "Basic statistics are processed by Jappix about some important things, you can find them below."
+msgstr "基本統計是由 Jappix 處理關於一些重要事物,你可以在下面找到它們。"
+
+msgid "Change your Jappix node configuration with this tool."
+msgstr "利用此工具變更你的 Jappix 節點設定。"
+
+msgid "Change the XMPP hosts that this Jappix node serve with this tool."
+msgstr "利用此工具變更此 Jappix 節點服務的 XMPP 主機。"
+
+msgid "All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"
+msgstr "所有此 Jappix 節點儲存的檔案可利用此工具管理:請選取子資料夾且開始編輯它的內容!"
+
+msgid "Jappix is fully customisable: you can change its design right here."
+msgstr "Jappix 可完全自訂:你可以在這邊變更它的設計。"
+
+msgid "This is not a valid image, please use PNG, GIF or JPG!"
+msgstr "這不是有效的影像,請使用 PNG、GIF 或 JPG!"
+
+msgid "The image could not be received, would you mind retry?"
+msgstr "影像無法被收到,你介意重試嗎?"
+
+msgid "Your image was added to the list!"
+msgstr "你的影像已被加入到清單!"
+
+msgid "Changes saved!"
+msgstr "變更已被儲存!"
+
+msgid "You can define more than one administrator for this Jappix node. You can also change a password with this tool."
+msgstr "你可以為此 Jappix 節點定義多位管理員。你也可以利用此工具變更密碼。"
+
+msgid "Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."
+msgstr "利用此工具更新你的 Jappix 節點,或檢查是否有新的可用。關於最新版本的資訊也會被顯示。"
+
+msgid "Access statistics"
+msgstr "存取統計"
+
+msgid "Share statistics"
+msgstr "分享統計"
+
+msgid "Other statistics"
+msgstr "其他統計"
+
+msgid "January"
+msgstr "1月"
+
+msgid "February"
+msgstr "2月"
+
+msgid "March"
+msgstr "3月"
+
+msgid "April"
+msgstr "4月"
+
+msgid "May"
+msgstr "5月"
+
+msgid "June"
+msgstr "6月"
+
+msgid "July"
+msgstr "7月"
+
+msgid "August"
+msgstr "8月"
+
+msgid "September"
+msgstr "9月"
+
+msgid "October"
+msgstr "10月"
+
+msgid "November"
+msgstr "11月"
+
+msgid "December"
+msgstr "12月"
+
+msgid "Monday"
+msgstr "星期一"
+
+msgid "Tuesday"
+msgstr "星期二"
+
+msgid "Wednesday"
+msgstr "星期三"
+
+msgid "Thursday"
+msgstr "星期四"
+
+msgid "Friday"
+msgstr "星期五"
+
+msgid "Saturday"
+msgstr "星期六"
+
+msgid "Sunday"
+msgstr "星期日"
+
+msgid "Total"
+msgstr "合計"
+
+msgid "Cache"
+msgstr "快取"
+
+msgid "Logs"
+msgstr "記錄"
+
+msgid "Music"
+msgstr "音樂"
+
+msgid "Backgrounds"
+msgstr "背景"
+
+msgid "Share"
+msgstr "分享"
+
+msgid "Background"
+msgstr "背景"
+
+msgid "Notice"
+msgstr "通知"
+
+msgid "Your design preferences have been saved!"
+msgstr "你的設計偏好已被儲存!"
+
+msgid "Please check your inputs: something is missing!"
+msgstr "請檢查你的輸入:漏了某些東西!"
+
+msgid "Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"
+msgstr "利用此工具變更你的 Jappix 節點背景。你可以設定自訂色彩或上傳的影像。釋出你的創造力!"
+
+msgid "Use default background"
+msgstr "使用預設的背景"
+
+msgid "Use your own image"
+msgstr "使用你自己的影像"
+
+msgid "Select a background to use and change the display options."
+msgstr "選取要使用的背景並變更顯示選項。"
+
+msgid "Use your own color"
+msgstr "使用你自己的顏色"
+
+msgid "Type the hexadecimal color value you want to use as a background."
+msgstr "輸入你要用來當作背景的 16 進位色彩值。"
+
+msgid "Manage backgrounds"
+msgstr "管理背景"
+
+msgid "You can add a new background to the list with this tool. Please send a valid image."
+msgstr ""
+
+msgid "If you want to remove some backgrounds, use the browser below."
+msgstr ""
+
+msgid "Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."
+msgstr ""
+
+msgid "Simple notice"
+msgstr "簡單通知"
+
+msgid "This notice only needs simple text to be displayed, but no code is allowed!"
+msgstr ""
+
+msgid "Advanced notice"
+msgstr "進階通知"
+
+msgid "You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."
+msgstr ""
+
+msgid "Available updates"
+msgstr "可用的更新"
+
+msgid "What's new?"
+msgstr "有什麼新鮮的?"
+
+msgid "Your storage folders are not writable, please apply the good rights!"
+msgstr "你的儲存空間資料夾無法寫入,請套用正確權限!"
+
+msgid "%1s may cause problems to the proxy, please increase %2s value up to %3s!"
+msgstr ""
+
+msgid "You are using a development version of Jappix. Update it through our repository by executing: %s."
+msgstr "你正在使用開發版本的 Jappix。從我們的存放區更新它請執行:%s。"
+
+msgid "A new Jappix version is available! Check what is new and launch the update!"
+msgstr "有新版本的 Jappix 可用!檢查有什麼新的並啟動更新!"
+
+msgid "Your version is out to date. Update it now to %s by clicking here!"
+msgstr "你的版本已經過時。在此點一下以便立刻更新!"
+
+msgid "Your version seems to be up to date, but you can check updates manually by clicking here."
+msgstr "你的版本似乎是最新的,但是你可以在此點一下以便手動檢查更新。"
+
+msgid "Check for updates"
+msgstr "檢查更新"
+
+msgid "Update in progress"
+msgstr "更新正在進行"
+
+msgid "Jappix has been updated: you are now running the latest version. Have fun!"
+msgstr "Jappix 已更新:你現在使用的是最新版本。祝你玩得愉快!"
+
+msgid "The update has failed! Please try again later."
+msgstr "更新失敗!請稍後重試。"
+
+msgid "Downloading package..."
+msgstr "正在下載套件..."
+
+msgid "Removing current Jappix system files..."
+msgstr "刪除目前的 Jappix 系統檔案..."
+
+msgid "Extracting package..."
+msgstr "正在取出套件..."
+
+msgid "Regenerating storage folder tree..."
+msgstr "重新產生儲存空間資料夾..."
+
+msgid "Jappix is now up to date!"
+msgstr "Jappix 現在是最新的!"
+
+msgid "Aborted: socket error!"
+msgstr "中止:socket 錯誤!"
+
+msgid "Aborted: buffer error!"
+msgstr "中止:緩衝器錯誤!"
+
+msgid "Aborted: everything is not writable!"
+msgstr "中止:全部都無法寫入!"
+
+msgid "Aborted: could not extract the package!"
+msgstr "中止:無法取出套件!"
+
+msgid "Visits"
+msgstr "訪問"
+
+msgid "Daily"
+msgstr "日"
+
+msgid "Weekly"
+msgstr "週"
+
+msgid "Monthly"
+msgstr "月"
+
+msgid "Yearly"
+msgstr "年"
+
+msgid "Size"
+msgstr "大小"
+
+msgid "Clean everything"
+msgstr "全部清除"
+
+msgid "Purge cache"
+msgstr "清除快取"
+
+msgid "Purge logs"
+msgstr "清除記錄"
+
+msgid "Purge updates"
+msgstr "清除更新"
+
+msgid "The storage folder you wanted to clean is now empty!"
+msgstr "你要清除的儲存空間資料夾是空的!"
+
+msgid "Keep your Jappix node fresh and fast, clean the storage folders regularly!"
+msgstr "保持你的 Jappix 節點清新與快速,定期清除儲存空間資料夾!"
+
+msgid "Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"
+msgstr "上傳你的音樂(Ogg Vorbis、MP3 或 WAV)以便可以在 Jappix 聆聽!"
+
+msgid "The file you want to upload must be smaller than %s."
+msgstr "你要上傳的檔案必須小於 %s。"
+
+msgid "Stay tuned in what your users store on your server and remove undesired content with this tool."
+msgstr ""
+
+msgid "Title"
+msgstr "標題"
+
+msgid "Artist"
+msgstr "藝人"
+
+msgid "Album"
+msgstr "專輯"
+
+msgid "File"
+msgstr "檔案"
+
+msgid "Upload"
+msgstr "上傳"
+
+msgid "The folder is empty."
+msgstr "資料夾是空的。"
+
+msgid "The music could not be received, please retry!"
+msgstr "音樂無法被收到,請重試!"
+
+msgid "This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"
+msgstr "這不是有效的音樂檔案,請用 Ogg Vorbis、MP3 或 WAV 編碼!"
+
+msgid "Your music has been added!"
+msgstr "你的音樂已被加入!"
+
+msgid "The selected elements have been removed."
+msgstr "選取的元素已被刪除。"
+
+msgid "You must select elements to remove!"
+msgstr "你必須選取要刪除的元素!"
+
+msgid "Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"
+msgstr "利用此工具加入新的使用者,或變更密碼(輸入已存在的使用者名稱)。請輸入安全的密碼!"
+
+msgid "Manage"
+msgstr "管理"
+
+msgid "List"
+msgstr "清單"
+
+msgid "Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."
+msgstr "利用此工具刪除使用者。注意你不能刪除僅存的那一位使用者。"
+
+msgid "The user has been added!"
+msgstr "使用者已被加入!"
+
+msgid "The chosen users have been removed."
+msgstr "選取的使用者已經被刪除。"
+
+msgid "You must select one or more users to be removed!"
+msgstr "你必須選取一或多位使用者以便刪除!"
+
+msgid "Yesterday"
+msgstr "昨日"
+
+msgid "%s days ago"
+msgstr "%s 日前"
+
+msgid "User currently active"
+msgstr "使用者目前活動中"
+
+msgid "Last seen: %s"
+msgstr "上次見到:%s"
+
+msgid "Inactive since: %s"
+msgstr "不活動自:%s"
+
+msgid "Your friend seems not to have received your message(s)!"
+msgstr "你的好友似乎沒收到你的訊息!"
+
+msgid "Static content server"
+msgstr "靜態內容伺服器"
+
+msgid "This is the static content server for %1s, “%2s”."
+msgstr "這是 %1s 用的靜態內容伺服器,“%2s”。"
+
+msgid "Suggested friends"
+msgstr "建議的好友"
+
+msgid "Check all"
+msgstr "全選"
+
+msgid "Uncheck all"
+msgstr "取消全選"
+
+msgid "Choose"
+msgstr "選取"
+
+msgid "List name"
+msgstr ""
+
+msgid "Allow"
+msgstr "允許"
+
+msgid "Deny"
+msgstr "拒絕"
+
+msgid "Group"
+msgstr "群組"
+
+msgid "Subscription"
+msgstr "訂閱"
+
+msgid "Both"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "Everybody"
+msgstr "每一位"
+
+msgid "Send messages"
+msgstr "傳送訊息"
+
+msgid "Send queries"
+msgstr "傳送查詢"
+
+msgid "See my status"
+msgstr "看我的狀態"
+
+msgid "Send his/her status"
+msgstr "傳送他的狀態"
+
+msgid "Everything"
+msgstr ""
+
+msgid "Item"
+msgstr "項目"
+
+msgid "Order"
+msgstr ""
+
+msgid "Active for this session"
+msgstr ""
+
+msgid "Always active"
+msgstr ""
+
+msgid "User directory"
+msgstr "使用者目錄"
+
+msgid "Search a friend"
+msgstr "搜尋好友"
+
+msgid "The feature requested is not implemented by the recipient or server and therefore cannot be processed."
+msgstr ""
+
+msgid "This is a repeat from %s"
+msgstr ""
+
+msgid "Loading comments..."
+msgstr "載入評論..."
+
+msgid "Type your comment here..."
+msgstr "在此輸入你的評論..."
+
+msgid "Could not get the comments!"
+msgstr "無法取得評論!"
+
+msgid "Show comments"
+msgstr "顯示評論"
+
+msgid "Send him/her a message"
+msgstr "傳送訊息給他"
+
+msgid "Start a chat with him/her"
+msgstr "開始與他聊天"
+
+msgid "Media integration"
+msgstr ""
+
+msgid "Comments locked!"
+msgstr ""
+
+msgid "Type something you want to share with your friends..."
+msgstr ""
+
+msgid "changed his/her nickname to %s"
+msgstr ""
+
+msgid "commented an item you follow: “%s”."
+msgstr ""
+
+msgid "Hide"
+msgstr ""
+
+msgid "liked your post: “%s”."
+msgstr ""
+
+msgid "quoted you somewhere: “%s”."
+msgstr ""
+
+msgid "published on your wall: “%s”."
+msgstr ""
+
+msgid "tagged you in a photo (%s)."
+msgstr ""
+
+msgid "tagged you in a video (%s)."
+msgstr ""
+
+msgid "Show"
+msgstr ""
+
+msgid "Need help? You'd better read our documentation page about how to fill this form!"
+msgstr ""
+
+msgid "Pubsub host"
+msgstr ""
+
+msgid "Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+msgstr ""
+
+msgid "Manager link"
+msgstr ""
+
+msgid "User uploads server"
+msgstr ""
+
+msgid "This is the user uploads server for %1s, “%2s”."
+msgstr ""
+
+msgid "Logo"
+msgstr ""
+
+msgid "You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"
+msgstr ""
+
+msgid "Upload each logo with the recommended maximum pixel size."
+msgstr ""
+
+msgid "This is not a valid image, please use the PNG format!"
+msgstr ""
+
+msgid "Your service logo has been successfully changed!"
+msgstr ""
+
+msgid "Your logo format must be PNG. Leave a field empty and the logo will not be changed."
+msgstr ""
+
+msgid "Remove this logo"
+msgstr ""
+
+msgid "View this logo"
+msgstr ""
+
+msgid "Send a file"
+msgstr ""
+
+msgid "Once uploaded, your friend will be prompted to download the file you sent."
+msgstr ""
+
+msgid "Groupchats to join"
+msgstr ""
+
+msgid "Purge sent files"
+msgstr ""
+
+msgid "would like to send you a file: “%s”."
+msgstr ""
+
+msgid "has accepted to received your file: “%s”."
+msgstr ""
+
+msgid "has rejected to receive your file: “%s”."
+msgstr ""
+
+msgid "could not receive your file: “%s”."
+msgstr ""
+
+msgid "has received a file exchange request: “%s”."
+msgstr ""
+
+msgid "Available shortcuts:"
+msgstr ""
+
+msgid "%s removes the chat logs"
+msgstr ""
+
+msgid "%s joins a groupchat"
+msgstr ""
+
+msgid "%s closes the chat"
+msgstr ""
+
+msgid "%s shows the user profile"
+msgstr ""
+
+msgid "%s sends a message to the room"
+msgstr ""
+
+msgid "%s changes your nickname"
+msgstr ""
+
+msgid "%s sends a message to someone in the room"
+msgstr ""
+
+msgid "%s changes the room topic"
+msgstr ""
+
+msgid "%s kicks an user of the room"
+msgstr ""
+
+msgid "%s bans an user of the room"
+msgstr ""
+
+msgid "%s invites someone to join the room"
+msgstr ""
+
+msgid "Social channel, chat and more."
+msgstr ""
+
+msgid "Create your public profile."
+msgstr ""
+
+msgid "A mini-chat for your website."
+msgstr ""
+
+msgid "Get Jappix, get support."
+msgstr ""
+
+msgid "Statistics around Jappix."
+msgstr ""
+
+msgid "Download Jappix for free."
+msgstr ""
+
+msgid "Find a public Jappix node."
+msgstr ""
+
+msgid "Public profile"
+msgstr ""
+
+msgid "Your profile anywhere on the Web."
+msgstr ""
+
+msgid "%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."
+msgstr ""
+
+msgid "Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year."
+msgstr ""
+
+msgid "You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genious improvement!"
+msgstr ""
+
+msgid "Yay, let's create my public profile!"
+msgstr ""
+
+msgid "Enable my public profile"
+msgstr ""
+
+#~ msgid "Jappix is a non-profit social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."
+#~ msgstr ""
+
+#~ msgid "See"
+#~ msgstr ""
+
+#~ msgid "Use default logo"
+#~ msgstr ""
+
+#~ msgid "Use your own logo"
+#~ msgstr ""
+
+#~ msgid "The recommended image format is PNG. Leave a field empty and the logo will not be changed."
+#~ msgstr ""
diff --git a/jappixmini/jappix/php/avatar-upload.php b/jappixmini/jappix/php/avatar-upload.php
new file mode 100644 (file)
index 0000000..73350e1
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the avatar upload PHP script for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// Set a special XML header
+header('Content-Type: text/xml; charset=utf-8');
+
+// No file uploaded?
+if((!isset($_FILES['file']) || empty($_FILES['file'])) || (!isset($_POST['id']) || empty($_POST['id'])))
+       exit(
+'<jappix xmlns=\'jappix:avatar:post\' id=\'0\'>
+       <error>bad-request</error>
+</jappix>'
+       );
+
+// Get the POST vars
+$id = $_POST['id'];
+$tmp_filename = $_FILES['file']['tmp_name'];
+$old_filename = $_FILES['file']['name'];
+
+// Get the file extension
+$ext = getFileExt($old_filename);
+
+// Hash it!
+$filename = md5($old_filename.time()).$ext;
+
+// Define some vars
+$path = JAPPIX_BASE.'/store/avatars/'.$filename;
+
+// Define MIME type
+if($ext == 'jpg')
+       $ext = 'jpeg';
+
+$mime = 'image/'.$ext;
+
+// Unsupported file extension?
+if(!preg_match('/^(jpeg|png|gif)$/i', $ext))
+       exit(
+'<jappix xmlns=\'jappix:avatar:post\' id=\''.$id.'\'>
+       <error>forbidden-type</error>
+</jappix>'
+       );
+
+// File upload error?
+if(!is_uploaded_file($tmp_filename) || !move_uploaded_file($tmp_filename, $path))
+       exit(
+'<jappix xmlns=\'jappix:file:post\' id=\''.$id.'\'>
+       <error>move-error</error>
+</jappix>'
+       );
+
+// Resize the image?
+if(!function_exists('gd_info') || resizeImage($path, $ext, 96, 96)) {
+       try {
+               // Encode the file
+               $binval = base64_encode(file_get_contents($path));
+               
+               // Remove the file
+               unlink($path);
+               
+               exit(
+'<jappix xmlns=\'jappix:file:post\' id=\''.$id.'\'>
+       <type>'.$mime.'</type>
+       <binval>'.$binval.'</binval>
+</jappix>'
+               );
+       }
+       
+       catch(Exception $e) {
+               // Remove the file
+               unlink($path);
+               
+               exit(
+'<jappix xmlns=\'jappix:file:post\' id=\''.$id.'\'>
+       <error>server-error</error>
+</jappix>'
+               );
+       }
+}
+
+// Remove the file
+unlink($path);
+
+// Something went wrong!
+exit(
+'<jappix xmlns=\'jappix:file:post\' id=\''.$id.'\'>
+       <error>service-unavailable</error>
+</jappix>'
+);
+
+?>
diff --git a/jappixmini/jappix/php/bosh.php b/jappixmini/jappix/php/bosh.php
new file mode 100644 (file)
index 0000000..4914d06
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the PHP BOSH proxy
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/01/12
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the configuration
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed?
+if(!BOSHProxy()) {
+       header('Status: 403 Forbidden', true, 403);
+       exit('HTTP/1.1 403 Forbidden');
+}
+
+// OPTIONS method?
+if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
+       // CORS headers
+       header('Access-Control-Allow-Origin: *');
+       header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
+       header('Access-Control-Allow-Headers: Content-Type');
+       header('Access-Control-Max-Age: 31536000');
+       
+       exit;
+}
+
+// Read POST content
+$data = file_get_contents('php://input');
+
+// POST method?
+if($data) {
+       // CORS headers
+       header('Access-Control-Allow-Origin: *');
+       header('Access-Control-Allow-Headers: Content-Type');
+       
+       $method = 'POST';
+}
+
+// GET method?
+else if(isset($_GET['data']) && $_GET['data'] && isset($_GET['callback']) && $_GET['callback']) {
+       $method = 'GET';
+       $data = $_GET['data'];
+       $callback = $_GET['callback'];
+}
+
+// Invalid method?
+else {
+       header('Status: 400 Bad Request', true, 400);
+       exit('HTTP/1.1 400 Bad Request');
+}
+
+// HTTP headers
+$headers = array('User-Agent: Jappix (BOSH PHP Proxy)', 'Connection: close', 'Content-Type: text/xml; charset=utf-8', 'Content-Length: '.strlen($data));
+
+// CURL is better if available
+if(function_exists('curl_init'))
+       $use_curl = true;
+else
+       $use_curl = false;
+
+// CURL stream functions
+if($use_curl) {
+       // Initialize CURL
+       $connection = curl_init(HOST_BOSH);
+       
+       // Set the CURL settings
+       curl_setopt($connection, CURLOPT_HEADER, 0);
+       curl_setopt($connection, CURLOPT_POST, 1);
+       curl_setopt($connection, CURLOPT_POSTFIELDS, $data);
+       curl_setopt($connection, CURLOPT_FOLLOWLOCATION, true);
+       curl_setopt($connection, CURLOPT_HTTPHEADER, $headers);
+       curl_setopt($connection, CURLOPT_VERBOSE, 0);
+       curl_setopt($connection, CURLOPT_CONNECTTIMEOUT, 30);
+       curl_setopt($connection, CURLOPT_TIMEOUT, 30);
+       curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 0);
+       curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 0);
+       curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
+       
+       // Get the CURL output
+       $output = curl_exec($connection);
+}
+
+// Built-in stream functions
+else {
+       // HTTP parameters
+       $parameters = array('http' => array(
+                                       'method' => 'POST',
+                                       'content' => $data
+                                     )
+                     );
+
+       $parameters['http']['header'] = $headers;
+
+       // Change default timeout
+       ini_set('default_socket_timeout', 30);
+
+       // Create the connection
+       $stream = @stream_context_create($parameters);
+       $connection = @fopen(HOST_BOSH, 'rb', false, $stream);
+
+       // Failed to connect!
+       if($connection == false) {
+               header('Status: 502 Proxy Error', true, 502);
+               exit('HTTP/1.1 502 Proxy Error');
+       }
+
+       // Allow stream blocking to handle incoming BOSH data
+       @stream_set_blocking($connection, true);
+
+       // Get the output content
+       $output = @stream_get_contents($connection);
+}
+
+// Cache headers
+header('Cache-Control: no-cache, must-revalidate');
+header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+
+// POST output
+if($method == 'POST') {
+       // XML header
+       header('Content-Type: text/xml; charset=utf-8');
+       
+       if(!$output)
+               echo('<body xmlns=\'http://jabber.org/protocol/httpbind\' type=\'terminate\'/>');
+       else
+               echo($output);
+}
+
+// GET output
+if($method == 'GET') {
+       // JSON header
+       header('Content-type: application/json');
+       
+       // Encode output to JSON
+       $json_output = json_encode($output);
+       
+       if(($output == false) || ($output == '') || ($json_output == 'null'))
+               echo($callback.'({"reply":"<body xmlns=\'http:\/\/jabber.org\/protocol\/httpbind\' type=\'terminate\'\/>"});');
+       else
+               echo($callback.'({"reply":'.$json_output.'});');
+}
+
+// Close the connection
+if($use_curl)
+       curl_close($connection);
+else
+       @fclose($connection);
+
+?>
diff --git a/jappixmini/jappix/php/desktop.php b/jappixmini/jappix/php/desktop.php
new file mode 100644 (file)
index 0000000..ceeb1a3
--- /dev/null
@@ -0,0 +1,181 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Desktop PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 16/01/12
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <title><?php echo htmlspecialchars(SERVICE_NAME); ?> &bull; <?php _e("An open social network"); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+       
+       <?php echoGetFiles($hash, '', 'css', 'desktop.xml', ''); echo "\n"; ?>
+       <!--[if lt IE 9]><?php echoGetFiles($hash, '', 'css', '', 'ie.css'); ?><![endif]-->
+       
+       <?php echoGetFiles($hash, $locale, 'js', 'desktop.xml', ''); echo "\n";
+       
+       if(anonymousMode()) {
+               echo "\n\t";
+               echoGetFiles($hash, '', 'css', 'anonymous.xml', '');
+               echo "\n\t";
+               echoGetFiles($hash, $locale, 'js', 'anonymous.xml', '');
+               echo "\n";
+       } ?>
+</head>
+
+<body class="body-images">
+
+<?php
+
+// Homepage?
+if(!anonymousMode()) { ?>
+       <!-- BEGIN HOMEPAGE -->
+       <div id="home">
+               <div class="home-images plane"></div>
+               
+               <div class="main">
+                       <div class="left">
+                               <div class="home-images logo"></div>
+                               <p class="upper"><?php _e("Communicate with the entire world!"); ?></p>
+                               <p class="secondary"><?php _e("Jappix is a great social platform, that you can access wherever you are, whenever you want and communicate with whovever you want."); ?></p>
+                               <p class="secondary"><?php _e("It allows you to get in touch with the millions of users who currently use the XMPP network like you do with Jappix. Join the community and stay free!"); ?></p>
+                       </div>
+                       
+                       <div class="right">
+                               <h1 class="top default"><?php _e("Hi there!"); ?></h1>
+                               
+                               <div class="default homediv">
+                                       <p><?php printf(T_("Welcome on %1s, “%2s”."), htmlspecialchars(SERVICE_NAME), htmlspecialchars(SERVICE_DESC)); ?></p>
+                                       
+                                       <p><?php _e("Login to your existing XMPP account or create a new one for free!"); ?></p>
+                                       
+                                       <button class="login buttons-images">
+                                               <span class="home-images"></span>
+                                               <span class="text"><?php _e("Login"); ?></span>
+                                       </button>
+                                       
+                                       <button class="register buttons-images">
+                                               <span class="home-images"></span>
+                                               <span class="text"><?php _e("Register"); ?></span>
+                                       </button>
+                                       
+                                       <p class="notice"><?php echo str_replace("PostPro", "<a href='http://www.post-pro.fr/'>PostPro</a>", T_("Jappix is an open-source project from PostPro, a non-profit organization which provides us a great help.")); ?></p>
+                               </div>
+                               
+                               <div class="navigation">
+                                       <?php
+                                       
+                                               // Keep get var
+                                               $keep_get = keepGet('m', false);
+                                       
+                                       ?>
+                                       <a class="home-images mobile" href="./?m=mobile<?php echo $keep_get; ?>"><?php _e("Mobile"); ?></a>
+                                       <?php if(showManagerLink()) { ?>
+                                       <a class="home-images manager" href="./?m=manager<?php echo $keep_get; ?>"><?php _e("Manager"); ?></a>
+                                       <?php } ?>
+                                       <a class="home-images project" href="https://project.jappix.com/"><?php _e("Project"); ?></a>
+                                       <?php if(sslCheck() && !httpsForce()) echo sslLink(); ?>
+                               </div>
+                       </div>
+               </div>
+               
+               <div class="home-images corporation">
+                       <div class="corp_network">
+                               <h2 class="nomargin">Jappix.com</h2>
+                               <div class="tabulate">
+                                       <a href="https://www.jappix.com/">
+                                               <span class="name">Jappix</span>
+                                               <span class="desc"><?php _e("Social channel, chat and more."); ?></span>
+                                       </a>
+                                       <a href="https://me.jappix.com/">
+                                               <span class="name">Jappix Me</span>
+                                               <span class="desc"><?php _e("Create your public profile."); ?></span>
+                                       </a>
+                                       <a href="https://mini.jappix.com/">
+                                               <span class="name">Jappix Mini</span>
+                                               <span class="desc"><?php _e("A mini-chat for your website."); ?></span>
+                                       </a>
+                                       <a href="https://project.jappix.com/">
+                                               <span class="name">Jappix Project</span>
+                                               <span class="desc"><?php _e("Get Jappix, get support."); ?></span>
+                                       </a>
+                                       <a href="https://stats.jappix.com/">
+                                               <span class="name">Jappix Stats</span>
+                                               <span class="desc"><?php _e("Statistics around Jappix."); ?></span>
+                                       </a>
+                               </div>
+                               
+                               <h2>Jappix.org</h2>
+                               <div class="tabulate">
+                                       <a href="http://jappix.org/">
+                                               <span class="name">Jappix Download</span>
+                                               <span class="desc"><?php _e("Download Jappix for free."); ?></span>
+                                       </a>
+                               </div>
+                               
+                               <h2>Jappix.net</h2>
+                               <div class="tabulate">
+                                       <a href="http://jappix.net/">
+                                               <span class="name">Jappix Network</span>
+                                               <span class="desc"><?php _e("Find a public Jappix node."); ?></span>
+                                       </a>
+                               </div>
+                       </div>
+               </div>
+               
+               <div class="locale" data-keepget="<?php echo(keepGet('l', false)); ?>">
+                       <div class="current">
+                               <div class="current_align"><?php echo(getLanguageName($locale)); ?></div>
+                       </div>
+               </div>
+               
+               <?php
+               
+                       // Add the notice
+                       $conf_notice = readNotice();
+                       $type_notice = $conf_notice['type'];
+                       $text_notice = $conf_notice['notice'];
+                       
+                       // Simple notice
+                       if(($type_notice == 'simple') || ($type_notice == 'advanced')) {
+                               // We must encode special HTML characters
+                               if($type_notice == 'simple')
+                                       $text_notice = '<span class="title home-images">'.T_("Notice").'</span><span class="text">'.htmlentities($text_notice).'</span>';
+                               
+                               // Echo the notice
+                               echo('<div class="notice '.$type_notice.'">'.$text_notice.'</div>');
+                       }
+               
+               ?>
+       </div>
+       <!-- END HOMEPAGE -->
+<?php } ?>
+
+<!-- BEGIN BOARD -->
+<div id="board">
+       <noscript class="one-board info visible"><?php _e("JavaScript is missing in your web browser, so that you will not be able to launch Jappix! Please fix this."); ?></noscript>
+</div>
+<!-- END BOARD -->
+
+</body>
+
+</html>
+
+<!-- Jappix <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/download-chat.php b/jappixmini/jappix/php/download-chat.php
new file mode 100644 (file)
index 0000000..3f28648
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the PHP script used to download a chat log
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// Send the HTML file to be downloaded
+if(isset($_GET['id']) && !empty($_GET['id']) && isSafe($_GET['id'])) {
+       // We define the variables
+       $filename = $_GET['id'];
+       $content_dir = '../store/logs/';
+       $filepath = $content_dir.$filename.'.html';
+       
+       // We set special headers
+       header("Content-disposition: attachment; filename=\"$filename.html\"");
+       header("Content-Type: application/force-download");
+       header("Content-Transfer-Encoding: text/html\n");
+       header("Content-Length: ".filesize($filepath));
+       header("Pragma: no-cache");
+       header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
+       header("Expires: 0");
+       readfile($filepath);
+       
+       // We delete the stored log file
+       unlink($filepath);
+}
+
+?>
diff --git a/jappixmini/jappix/php/drawsvgchart.php b/jappixmini/jappix/php/drawsvgchart.php
new file mode 100644 (file)
index 0000000..837f343
--- /dev/null
@@ -0,0 +1,495 @@
+<?php
+
+//   Extracted from CodingTeam for the Jappix project.
+
+//   This file is a part of CodingTeam. Take a look at <http://codingteam.org>.
+//   Copyright © 2007-2010 Erwan Briand <erwan@codingteam.net>
+//
+//   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, version 3 only.
+//
+//   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/>.
+
+/**
+ * @file
+ * This file contains the DrawSVGChart class.
+ */
+
+/**
+ * DrawSVGChart class
+ */
+class DrawSVGChart {
+    private $datas, $legend, $link, $xml_object, $svg,
+            $xml_elements, $evolution;
+    public $has_errors;
+
+    function createChart($datas=array(), $legend=array(), $link,
+                         $evolution=FALSE, $type='others')
+    {
+        $this->has_errors = FALSE;
+        $max = 0;
+
+        // One or two data arrays
+        if (isset($datas[0]) && is_array($datas[0]))
+        {
+            $datas_number = count($datas[0]);
+
+            if ($datas_number >= 1)
+                $max = max($datas[0]);
+            else
+                $this->has_errors = TRUE;
+        }
+        else
+        {
+            $datas_number = count($datas);
+
+            if ($datas_number >= 1)
+                $max = max($datas);
+            else
+                $this->has_errors = TRUE;
+        }
+
+        // Set the width of the chart
+        if ($datas_number * 55 > 400)
+            $width = $datas_number * 55;
+        else
+            $width = 400;
+
+        $height = 250;
+        $this->datas = $datas;
+        $this->legend = $legend;
+        $this->link = $link;
+        $this->evolution = $evolution;
+        $this->type = $type;
+        $this->xml_elements = array();
+
+        // Scale
+        if ($max <= 20)
+        {
+            $scale[4] = 20;
+            $scale[3] = 15;
+            $scale[2] = 10;
+            $scale[1] = 5;
+        }
+        else
+        {
+            $scale[4] = ceil($max / 20) * 20;
+            $scale[3] = $scale[4] * 3/4;
+            $scale[2] = $scale[4] * 2/4;
+            $scale[1] = $scale[4] * 1/4;
+        }
+
+        if ($scale[4] == 0 || $max == 0)
+            $this->has_errors = TRUE;
+
+        if ($this->has_errors)
+            return TRUE;
+
+        $this->xml_object = new DOMDocument('1.0', 'utf-8');
+       
+       // Process the static file host prefix
+       $static_prefix = '.';
+       
+       if(hasStatic())
+               $static_prefix = HOST_STATIC.'/php';
+       
+        // Add the stylesheet
+        $style = $this->xml_object->createProcessingInstruction("xml-stylesheet",
+                 "type='text/css' href='".getFiles(genHash(getVersion()), '', 'css', '', 'stats-svg.css')."'");
+        $this->xml_object->appendChild($style);
+
+        // Create the root SVG element
+        $this->svg = $this->xml_object->createElement('svg');
+        $this->svg->setAttribute('xmlns:svg', 'http://www.w3.org/2000/svg');
+        $this->svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
+        $this->svg->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
+        $this->svg->setAttribute('version', '1.1');
+        $this->svg->setAttribute('width', $width);
+        $this->svg->setAttribute('height', $height);
+        $this->svg->setAttribute('id', 'svg');
+        $this->xml_object->appendChild($this->svg);
+
+        // Create a definition
+        $this->xml_elements['basic_defs'] = $this->xml_object->createElement('defs');
+        $path = $this->xml_object->createElement('path');
+        $path->setAttribute('id', 'mark');
+        $path->setAttribute('d', 'M 0,234 v 4 ');
+        $path->setAttribute('stroke', '#596171');
+        $path->setAttribute('stroke-width', '2px');
+        $this->xml_elements['basic_defs']->appendChild($path);
+
+        // Create the static background
+        $this->xml_elements['static_background'] = $this->xml_object->createElement('g');
+        $this->xml_elements['static_background']->setAttribute('class', 'static-background');
+
+        // Draw the legend
+        $this->drawLegend();
+
+        // Draw the table
+        $this->drawTable($scale, $width);
+
+        // Draw the chart
+        $this->drawChart($scale, $width);
+    }
+
+    function drawLegend()
+    {
+        $pstart = 3;
+        $tstart = 7;
+
+        foreach ($this->legend as $item)
+        {
+            $val_path = $pstart + 11;
+            $val_text = $tstart + 10;
+
+            // Create the legend line
+            $path = $this->xml_object->createElement('path');
+            $path->setAttribute('d', 'M 40, '.$val_path.' L 55, '.$val_path);
+            $path->setAttribute('id', 'legendline');
+            $path->setAttribute('stroke', $item[0]);
+            $path->setAttribute('stroke-width', '2px');
+
+            // Create the legend text
+            $text = $this->xml_object->createElement('text', $item[1]);
+            $text->setAttribute('x', 57);
+            $text->setAttribute('y', $val_text);
+            $text->setAttribute('text-anchor', 'start');
+            $text->setAttribute('id', 'reftext');
+            $text->setAttribute('fill', $item[0]);
+            $text->setAttribute('font-size', '11px');
+            $text->setAttribute('font-family', "'DejaVu sans', Verdana, sans-serif");
+
+            // Append elemets
+            $this->xml_elements['static_background']->appendChild($path);
+            $this->xml_elements['static_background']->appendChild($text);
+
+            $pstart = $val_path;
+            $tstart = $val_text;
+        }
+    }
+
+    function drawTable($scale, $width)
+    {
+        // Create left scale
+        $top = TRUE;
+        $start = -17;
+
+        foreach ($scale as $level)
+        {
+            $type = $this->type;
+            
+            if(($type == 'share') || ($type == 'others'))
+                $level = formatBytes($level);
+            
+            if ($top)
+                $color = '#CED0D5';
+            else
+                $color = '#EAEAEA';
+
+            $m = $start + 50;
+
+            $path = $this->xml_object->createElement('path');
+            $path->setAttribute('d', 'M 38, '.$m.' L '.$width.', '.$m);
+            $path->setAttribute('stroke', $color);
+            $path->setAttribute('stroke-width', '1px');
+
+            $text = $this->xml_object->createElement('text', $level);
+            $text->setAttribute('x', 34);
+            $text->setAttribute('y', ($m + 3));
+            $text->setAttribute('text-anchor', 'end');
+            $text->setAttribute('class', 'refleft');
+
+            $this->xml_elements['static_background']->appendChild($path);
+            $this->xml_elements['static_background']->appendChild($text);
+
+            $top = FALSE;
+            $start = $m;
+        }
+
+        // Add zero
+        $text = $this->xml_object->createElement('text', 0);
+        $text->setAttribute('x', 34);
+        $text->setAttribute('y', 236);
+        $text->setAttribute('text-anchor', 'end');
+        $text->setAttribute('class', 'refleft');
+
+        $this->xml_elements['static_background']->appendChild($text);
+    }
+
+    function drawChart($scale, $width)
+    {
+        if (isset($this->datas[0]) && is_array($this->datas[0]))
+        {
+            $foreached_datas = $this->datas[0];
+            $onlykeys_datas = array_keys($this->datas[0]);
+            $secondary_datas = array_keys($this->datas[1]);
+        }
+        else
+        {
+            $foreached_datas = $this->datas;
+            $onlykeys_datas = array_keys($this->datas);
+            $secondary_datas = FALSE;
+        }
+
+        // Create graphics data
+        $defs = $this->xml_object->createElement('defs');
+
+        $rect = $this->xml_object->createElement('rect');
+        $rect->setAttribute('id', 'focusbar');
+        $rect->setAttribute('width', 14);
+        $rect->setAttribute('height', 211);
+        $rect->setAttribute('x', -20);
+        $rect->setAttribute('y', 34);
+        $rect->setAttribute('style', 'fill: black; opacity: 0;');
+        $defs->appendChild($rect);
+
+        $path = $this->xml_object->createElement('path');
+        $path->setAttribute('id', 'bubble');
+
+        if ($this->evolution)
+            $path->setAttribute('d', 'M 4.7871575,0.5 L 39.084404,0.5 C 41.459488,0.5 43.371561,2.73 43.371561,5.5 L 43.371561,25.49999 L 43.30,31.05 L 4.7871575,30.49999 C 2.412072,30.49999 0.5,28.26999 0.5,25.49999 L 0.5,5.5 C 0.5,2.73 2.412072,0.5 4.7871575,0.5 z');
+        elseif ($secondary_datas)
+            $path->setAttribute('d', 'M 1,0 v 8 l -6,-10 c -1.5,-2 -1.5,-2 -6,-2 h -36                        c -3,0 -6,-3 -6,-6 v -28 c 0,-3 3,-6 6,-6 h 43 c 3,0 6,3 6,6 z');
+        else
+            $path->setAttribute('d', 'M 4.7871575,0.5 L 39.084404,0.5 C 41.459488,0.5 43.371561,2.73 43.371561,5.5 L 43.371561,25.49999 C 43.371561,27.07677 43.83887,41.00777 42.990767,40.95796 C 42.137828,40.90787 37.97451,30.49999 36.951406,30.49999 L 4.7871575,30.49999 C 2.412072,30.49999 0.5,28.26999 0.5,25.49999 L 0.5,5.5 C 0.5,2.73 2.412072,0.5 4.7871575,0.5 z');
+
+        $path->setAttribute('fill', 'none');
+        $path->setAttribute('fill-opacity', '0.85');
+        $path->setAttribute('pointer-events', 'none');
+        $path->setAttribute('stroke-linejoin', 'round');
+        $path->setAttribute('stroke', 'none');
+        $path->setAttribute('stroke-opacity', '0.8');
+        $path->setAttribute('stroke-width', '1px');
+        $defs->appendChild($path);
+
+        $rect = $this->xml_object->createElement('rect');
+        $rect->setAttribute('id', 'graphicbar');
+        $rect->setAttribute('width', '12');
+        $rect->setAttribute('height', '200');
+        $rect->setAttribute('rx', '2');
+        $rect->setAttribute('ry', '1');
+        $rect->setAttribute('fill', '#6C84C0');
+        $rect->setAttribute('fill-opacity', '0.6');
+        $rect->setAttribute('stroke', '#5276A9');
+        $rect->setAttribute('stroke-width', '1px');
+        $defs->appendChild($rect);
+
+        $rect = $this->xml_object->createElement('rect');
+        $rect->setAttribute('style', 'fill:#8B2323');
+        $rect->setAttribute('id', 'rectpoint');
+        $rect->setAttribute('width', 4);
+        $rect->setAttribute('height', 4);
+        $defs->appendChild($rect);
+
+        $this->xml_elements['chart_defs'] = $defs;
+        $global_g = $this->xml_object->createElement('g');
+
+        // Calc
+        $x_base = 35;
+        $y_base = 20;
+        $start = 18;
+        $element = 0;
+
+        $chart_defs = '';
+        $xprevious = 38;
+        $tprevious = 233;
+
+        foreach ($foreached_datas as $key => $data)
+        {
+            $x = 27 + $x_base;
+            $y = 107 + $y_base;
+
+            $top = 233 - ceil($data / ($scale[4] / 100) * 2);
+
+            if ($top <= 50)
+                $bubble_top = 55;
+            elseif (!$secondary_datas)
+                $bubble_top = ($top - 42);
+            elseif ($secondary_datas)
+                $bubble_top = ($top - 10);
+
+            $type = $this->type;
+
+            if(($type == 'share') || ($type == 'others'))
+                $value = formatBytes($data);
+            else
+                $value = $data;
+            
+            // Create the chart with datas
+            $g = $this->xml_object->createElement('g');
+            $g->setAttribute('transform', 'translate('.$x.')');
+
+            $duse = $this->xml_object->createElement('use');
+            $duse->setAttribute('xlink:href', '#mark');
+            $duse->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
+            $g->appendChild($duse);
+
+            $data_g = $this->xml_object->createElement('g');
+            $data_g->setAttribute('class', 'gbar');
+
+            if ($this->link)
+            {
+                $text = $this->xml_object->createElement('text');            
+
+                $link = $this->xml_object->createElement('a', mb_substr(filterSpecialXML($onlykeys_datas[$element]), 0, 7));
+                $link->setAttribute('xlink:href', str_replace('{data}', filterSpecialXML($onlykeys_datas[$element]), $this->link));
+                $link->setAttribute('target', '_main');
+                $text->appendChild($link);
+            }
+            else
+                $text = $this->xml_object->createElement('text', mb_substr(filterSpecialXML($onlykeys_datas[$element]), 0, 7));
+
+            $text->setAttribute('class', 'reftext');
+            $text->setAttribute('y', 248);
+            $text->setAttribute('text-anchor', 'middle');
+
+            $data_g->appendChild($text);
+
+            $uselink = $this->xml_object->createElement('use');
+            $uselink->setAttribute('xlink:href', '#focusbar');
+            $uselink->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
+            $data_g->appendChild($uselink);
+
+            if (!$this->evolution)
+            {
+                $rect = $this->xml_object->createElement('rect');
+                $rect->setAttribute('class', 'bluebar');
+                $rect->setAttribute('height', (233 - $top));
+                $rect->setAttribute('width', 13);
+                $rect->setAttribute('x', -6);
+                $rect->setAttribute('y', $top);
+                $rect->setAttribute('fill', $this->legend[0][0]);
+                $rect->setAttribute('fill-opacity', '0.6');
+                $data_g->appendChild($rect);
+            }
+            else
+            {
+                $use = $this->xml_object->createElement('use');
+                $use->setAttribute('xlink:href', '#rectpoint');
+                $use->setAttribute('y', ($top - 1));
+                $use->setAttribute('x', -2);
+                $data_g->appendChild($use);
+
+                if ($x != (35 + 27))
+                    $chart_defs .= 'L '.$x.' '.$top.'  ';
+                else
+                    $chart_defs .= 'M '.$xprevious.' '.$tprevious.' L '.$x.' '.$top.'  ';
+
+                $xprevious = $x;
+                $tprevious = $top;
+            }
+
+            if ($secondary_datas && isset($secondary_datas[$element]))
+            {
+                $datalink = $secondary_datas[$element];
+                $dataval = $this->datas[1][$datalink];
+                $stop = 233 - ceil($dataval / ($scale[4] / 100) * 2);
+
+                $rect = $this->xml_object->createElement('rect');
+                $rect->setAttribute('class', 'redbar');
+                $rect->setAttribute('height', (233 - $stop));
+                $rect->setAttribute('width', 13);
+                $rect->setAttribute('x', -6);
+                $rect->setAttribute('y', $stop);
+                $rect->setAttribute('fill', $this->legend[1][0]);
+                $rect->setAttribute('fill-opacity', '0.7');
+                $data_g->appendChild($rect);
+            }
+
+            if (!$this->evolution)
+            {
+                $path = $this->xml_object->createElement('path');
+                $path->setAttribute('stroke', '#5276A9');
+                $path->setAttribute('stroke-width', '2px');
+                $path->setAttribute('fill', 'none');
+                $path->setAttribute('d', 'M -7,233 v -'.(232 - $top).' c 0,-1 1,-1 1,-1 h 12 c 1,0 2,0 2,1 v '.(232 - $top).' z');
+                $data_g->appendChild($path);
+            }
+
+            $uselink = $this->xml_object->createElement('use');
+            $uselink->setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
+            $uselink->setAttribute('xlink:href', '#bubble');
+            $uselink->setAttribute('y', $bubble_top);
+
+            if (!$secondary_datas)
+                $uselink->setAttribute('x', -42);
+
+            $data_g->appendChild($uselink);
+
+            $text = $this->xml_object->createElement('text', $value);
+            $text->setAttribute('class', 'bubbletextblue');
+            $text->setAttribute('x', -10);
+
+            if (!$secondary_datas)
+                $text->setAttribute('y', ($bubble_top + 20));
+            else
+                $text->setAttribute('y', ($bubble_top - 27));
+
+            $text->setAttribute('fill', 'none');
+            $data_g->appendChild($text);
+
+            if ($secondary_datas && isset($secondary_datas[$element]))
+            {
+                $text = $this->xml_object->createElement('text', $dataval);
+                $text->setAttribute('class', 'bubbletextred');
+                $text->setAttribute('x', -10);
+                $text->setAttribute('y', ($bubble_top - 11));
+                $text->setAttribute('fill', 'none');
+                $data_g->appendChild($text);
+            }
+
+            $g->appendChild($data_g);
+            $global_g->appendChild($g);
+
+            $x_base = $x_base + 50;
+            $y_base = $y_base + 20;
+            $element ++;            
+        }
+
+        if ($this->evolution)
+        {
+            $path = $this->xml_object->createElement('path');
+            $path->setAttribute('d', $chart_defs);
+            $path->setAttribute('stroke', $this->legend[0][0]);
+            $path->setAttribute('stroke-width', '1px');
+            $path->setAttribute('fill', 'none');
+            $this->xml_elements['evolution_path'] = $path;
+        }
+
+        $this->xml_elements['global_g'] = $global_g;
+
+        $path = $this->xml_object->createElement('path');
+        $path->setAttribute('d', 'M 38,233 h '.$width);
+        $path->setAttribute('stroke', '#2F4F77');
+        $path->setAttribute('stroke-width', '2px');
+        $path->setAttribute('pointer-events', 'none');
+        $this->xml_elements['final_path'] = $path;
+    }
+
+    function has_errors()
+    {
+        return $this->has_errors;
+    }
+
+    function getXMLOutput()
+    {
+        if (isset($this->xml_object))
+        {
+            // Add SVG elements to the DOM object
+            foreach($this->xml_elements as $element)
+                $this->svg->appendChild($element);
+
+            // Return the XML
+            $this->xml_object->formatOutput = true; 
+            return $this->xml_object->saveXML();
+        }
+    }
+}
+?>
diff --git a/jappixmini/jappix/php/file-share.php b/jappixmini/jappix/php/file-share.php
new file mode 100644 (file)
index 0000000..39d4eb8
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix microblog file attaching script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 14/01/12
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// Set a special XML header
+header('Content-Type: text/xml; charset=utf-8');
+
+// Everything is okay
+if((isset($_FILES['file']) && !empty($_FILES['file'])) && (isset($_POST['user']) && !empty($_POST['user'])) && (isset($_POST['location']) && !empty($_POST['location']))) {
+       // Get the user name
+       $user = $_POST['user'];
+       
+       // Get the file name
+       $tmp_filename = $_FILES['file']['tmp_name'];
+       $filename = $_FILES['file']['name'];
+       
+       // Get the location
+       if(HOST_UPLOAD)
+               $location = HOST_UPLOAD;
+       else
+               $location = $_POST['location'];
+       
+       // Get the file new name
+       $ext = getFileExt($filename);
+       $new_name = preg_replace('/(^)(.+)(\.)(.+)($)/i', '$2', $filename);
+       
+       // Define some vars
+       $content_dir = JAPPIX_BASE.'/store/share/'.$user;
+       $security_file = $content_dir.'/index.html';
+       $name = sha1(time().$filename);
+       $path = $content_dir.'/'.$name.'.'.$ext;
+       $thumb_xml = '';
+       
+       // Forbidden file?
+       if(!isSafe($filename) || !isSafe($name.'.'.$ext)) {
+               exit(
+'<jappix xmlns=\'jappix:file:post\'>
+       <error>forbidden-type</error>
+</jappix>'
+               );
+       }
+       
+       // Create the user directory
+       if(!is_dir($content_dir)) {
+               mkdir($content_dir, 0777, true);
+               chmod($content_dir, 0777);
+       }
+       
+       // Create (or re-create) the security file
+       if(!file_exists($security_file))        
+               file_put_contents($security_file, securityHTML());
+       
+       // File upload error?
+       if(!is_uploaded_file($tmp_filename) || !move_uploaded_file($tmp_filename, $path)) {
+               exit(
+'<jappix xmlns=\'jappix:file:post\'>
+       <error>move-error</error>
+</jappix>'
+               );
+       }
+       
+       // Resize and compress if this is a JPEG file
+       if(preg_match('/^(jpg|jpeg|png|gif)$/i', $ext)) {
+               // Resize the image
+               resizeImage($path, $ext, 1024, 1024);
+               
+               // Copy the image
+               $thumb = $content_dir.'/'.$name.'_thumb.'.$ext;
+               copy($path, $thumb);
+               
+               // Create the thumbnail
+               if(resizeImage($thumb, $ext, 140, 105))
+                       $thumb_xml = '<thumb>'.htmlspecialchars($location.'store/share/'.$user.'/'.$name.'_thumb.'.$ext).'</thumb>';
+       }
+       
+       // Return the path to the file
+       exit(
+'<jappix xmlns=\'jappix:file:post\'>
+       <href>'.htmlspecialchars($location.'store/share/'.$user.'/'.$name.'.'.$ext).'</href>
+       <title>'.htmlspecialchars($new_name).'</title>
+       <type>'.htmlspecialchars(getFileMIME($path)).'</type>
+       <length>'.htmlspecialchars(filesize($path)).'</length>
+       '.$thumb_xml.'
+</jappix>'
+       );
+}
+
+// Bad request error!
+exit(
+'<jappix xmlns=\'jappix:file:post\'>
+       <error>bad-request</error>
+</jappix>'
+);
+
+?>
diff --git a/jappixmini/jappix/php/form-hosts.php b/jappixmini/jappix/php/form-hosts.php
new file mode 100644 (file)
index 0000000..414dd4e
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the hosts configuration form (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 11/06/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+<a class="info smallspace neutral" href="http://codingteam.net/project/jappix/doc/JappixApp#title-3" target="_blank"><?php _e("Need help? You'd better read our documentation page about how to fill this form!"); ?></a>
+
+<fieldset>
+       <legend><?php _e("General"); ?></legend>
+       
+       <label for="host_main"><?php _e("Main host"); ?></label><input id="host_main" type="text" name="host_main" value="<?php echo $host_main; ?>" pattern="[^@/]+" />
+       
+       <label for="host_muc"><?php _e("Groupchat host"); ?></label><input id="host_muc" type="text" name="host_muc" value="<?php echo $host_muc; ?>" pattern="[^@/]+" />
+       
+       <label for="host_pubsub"><?php _e("Pubsub host"); ?></label><input id="host_pubsub" type="text" name="host_pubsub" value="<?php echo $host_pubsub; ?>" pattern="[^@/]+" />
+</fieldset>
+
+<fieldset>
+       <legend><?php _e("Advanced"); ?></legend>
+       
+       <label for="host_anonymous"><?php _e("Anonymous host"); ?></label><input id="host_anonymous" type="text" name="host_anonymous" value="<?php echo $host_anonymous; ?>" pattern="[^@/]+" />
+       
+       <label for="host_vjud"><?php _e("Directory host"); ?></label><input id="host_vjud" type="text" name="host_vjud" value="<?php echo $host_vjud; ?>" pattern="[^@/]+" />
+       
+       <label for="host_bosh"><?php _e("BOSH host"); ?></label><input id="host_bosh" type="text" name="host_bosh" value="<?php echo $host_bosh; ?>" />
+       
+       <input type="hidden" name="host_bosh_main" value="<?php echo $host_bosh_main; ?>" />
+       
+       <input type="hidden" name="host_bosh_mini" value="<?php echo $host_bosh_mini; ?>" />
+       
+       <input type="hidden" name="host_static" value="<?php echo $host_static; ?>" />
+       
+       <input type="hidden" name="host_upload" value="<?php echo $host_upload; ?>" />
+</fieldset>
diff --git a/jappixmini/jappix/php/form-main.php b/jappixmini/jappix/php/form-main.php
new file mode 100644 (file)
index 0000000..02a1627
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the main configuration form (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, LinkMauve
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Checks the checkboxes which are set "on"
+$checked = ' checked=""';
+
+// Host locking
+if($lock_host == 'on')
+       $check_lock_host = $checked;
+else
+       $check_lock_host = '';
+
+// Anonymous mode
+if($anonymous_mode == 'on')
+       $check_anonymous_mode = $checked;
+else
+       $check_anonymous_mode = '';
+
+// Registration
+if($registration == 'on')
+       $check_registration = $checked;
+else
+       $check_registration = '';
+
+// BOSH proxy
+if($bosh_proxy == 'on')
+       $check_bosh_proxy = $checked;
+else
+       $check_bosh_proxy = '';
+
+// Manager link
+if($manager_link == 'on')
+       $check_manager_link = $checked;
+else
+       $check_manager_link = '';
+
+// Encryption
+if($encryption == 'on')
+       $check_encryption = $checked;
+else
+       $check_encryption = '';
+
+// HTTPS storage
+if($https_storage == 'on')
+       $check_https_storage = $checked;
+else
+       $check_https_storage = '';
+
+// Force HTTPS
+if($https_force == 'on')
+       $check_https_force = $checked;
+else
+       $check_https_force = '';
+
+// Compression
+if($compression == 'on')
+       $check_compression = $checked;
+else
+       $check_compression = '';
+
+?>
+
+<a class="info smallspace neutral" href="http://codingteam.net/project/jappix/doc/JappixApp#title-2" target="_blank"><?php _e("Need help? You'd better read our documentation page about how to fill this form!"); ?></a>
+
+<fieldset>
+       <legend><?php _e("Service"); ?></legend>
+       
+       <label for="service_name"><?php _e("Service name"); ?></label><input id="service_name" type="text" name="service_name" value="<?php echo $service_name; ?>" maxlength="14" />
+       
+       <label for="service_desc"><?php _e("Service description"); ?></label><input id="service_desc" type="text" name="service_desc" value="<?php echo $service_desc; ?>" maxlength="30" />
+</fieldset>
+
+<fieldset>
+       <legend><?php _e("Connection"); ?></legend>
+       
+       <label for="jappix_resource"><?php _e("Resource"); ?></label><input id="jappix_resource" type="text" name="jappix_resource" value="<?php echo $jappix_resource; ?>" maxlength="1023" />
+       
+       <label for="lock_host"><?php _e("Lock the host"); ?></label><input id="lock_host" type="checkbox" name="lock_host"<?php echo $check_lock_host; ?> />
+       
+       <label for="anonymous_mode"><?php _e("Anonymous mode"); ?></label><input id="anonymous_mode" type="checkbox" name="anonymous_mode"<?php echo $check_anonymous_mode; ?> />
+       
+       <label for="registration"><?php _e("Registration allowed"); ?></label><input id="registration" type="checkbox" name="registration"<?php echo $check_registration; ?> />
+       
+       <label for="bosh_proxy"><?php _e("Use a proxy"); ?></label><input id="bosh_proxy" type="checkbox" name="bosh_proxy"<?php echo $check_bosh_proxy; ?> />
+</fieldset>
+
+<fieldset>
+       <legend><?php _e("Others"); ?></legend>
+       
+       <label for="manager_link"><?php _e("Manager link"); ?></label><input id="manager_link" type="checkbox" name="manager_link"<?php echo $check_manager_link; ?> />
+       
+       <label for="groupchats_join"><?php _e("Groupchats to join"); ?></label><input id="groupchats_join" type="text" name="groupchats_join" value="<?php echo $groupchats_join; ?>" placeholder="postpro@muc.jappix.com, mini@muc.jappix.com" />
+</fieldset>
+
+<fieldset>
+       <legend><?php _e("Advanced"); ?></legend>
+       
+       <label for="encryption"><?php _e("Encryption"); ?></label><input id="encryption" type="checkbox" name="encryption"<?php echo $check_encryption; ?> />
+       
+       <label for="https_storage"><?php _e("HTTPS storage"); ?></label><input id="https_storage" type="checkbox" name="https_storage"<?php echo $check_https_storage; ?> />
+       
+       <label for="https_force"><?php _e("Force HTTPS"); ?></label><input id="https_force" type="checkbox" name="https_force"<?php echo $check_https_force; ?> />
+       
+       <label for="compression"><?php _e("Compression"); ?></label><input id="compression" type="checkbox" name="compression"<?php echo $check_compression; ?> />
+       
+       <input type="hidden" name="multi_files" value="<?php echo $multi_files; ?>" />
+       
+       <input type="hidden" name="developer" value="<?php echo $developer; ?>" />
+</fieldset>
diff --git a/jappixmini/jappix/php/form-users.php b/jappixmini/jappix/php/form-users.php
new file mode 100644 (file)
index 0000000..4e31343
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the user add form (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 08/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+
+<fieldset>
+       <legend><?php _e("New"); ?></legend>
+       
+       <label for="user_name"><?php _e("User"); ?></label><input id="user_name" class="icon <?php echo($form_parent); ?>-images" type="text" name="user_name" value="<?php echo(htmlspecialchars($user_name)); ?>" maxlength="30" />
+       
+       <label for="user_password"><?php _e("Password"); ?></label><input id="user_password" class="icon <?php echo($form_parent); ?>-images" type="password" name="user_password" maxlength="40" />
+       
+       <label for="user_repassword"><?php _e("Confirm"); ?></label><input id="user_repassword" class="icon <?php echo($form_parent); ?>-images" type="password" name="user_repassword" maxlength="40" />
+</fieldset>
diff --git a/jappixmini/jappix/php/functions-get.php b/jappixmini/jappix/php/functions-get.php
new file mode 100644 (file)
index 0000000..9b91e6f
--- /dev/null
@@ -0,0 +1,280 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the PHP functions for Jappix Get API
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Mathieui, olivierm
+Last revision: 26/08/11
+
+*/
+
+// The function to get the cached content
+function readCache($hash) {
+       return file_get_contents(JAPPIX_BASE.'/store/cache/'.$hash.'.cache');
+}
+
+// The function to generate a cached file
+function genCache($string, $mode, $cache) {
+       if(!$mode) {
+               $cache_dir = JAPPIX_BASE.'/store/cache';
+               $file_put = $cache_dir.'/'.$cache.'.cache';
+               
+               // Cache not yet wrote
+               if(is_dir($cache_dir) && !file_exists($file_put))
+                       file_put_contents($file_put, $string);
+       }
+}
+
+// The function to remove the BOM from a string
+function rmBOM($string) { 
+       if(substr($string, 0, 3) == pack('CCC', 0xef, 0xbb, 0xbf))
+               $string = substr($string, 3);
+       
+       return $string; 
+}
+
+// The function to compress the CSS
+function compressCSS($buffer) {
+       // We remove the comments
+       $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
+       
+       // We remove the useless spaces
+       $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
+       
+       // We remove the last useless spaces
+       $buffer = str_replace(array(' { ',' {','{ '), '{', $buffer);
+       $buffer = str_replace(array(' } ',' }','} '), '}', $buffer);
+       $buffer = str_replace(array(' : ',' :',': '), ':', $buffer);
+       
+       return $buffer;
+}
+
+// The function to replace classical path to get.php paths
+function setPath($string, $hash, $host, $type, $locale) {
+       // Initialize the static server path
+       $static = '.';
+       
+       // Replace the JS strings
+       if($type == 'js') {
+               // Static host defined
+               if($host && ($host != '.'))
+                       $static = $host;
+               
+               // Links to JS (must have a lang parameter)
+               $string = preg_replace('/((\")|(\'))(\.\/)(js)(\/)(\S+)(js)((\")|(\'))/', '$1'.$static.'/php/get.php?h='.$hash.'&l='.$locale.'&t=$5&f=$7$8$9', $string);
+               
+               // Other "normal" links (no lang parameter)
+               $string = preg_replace('/((\")|(\'))(\.\/)(css|img|store|snd)(\/)(\S+)(css|png|jpg|jpeg|gif|bmp|ogg|oga)((\")|(\'))/', '$1'.$static.'/php/get.php?h='.$hash.'&t=$5&f=$7$8$9', $string);
+       }
+       
+       // Replace the CSS strings
+       else if($type == 'css') {
+               // Static host defined
+               if($host && ($host != '.'))
+                       $static = $host.'/php';
+               
+               $string = preg_replace('/(\(\.\.\/)(css|js|img|store|snd)(\/)(\S+)(css|js|png|jpg|jpeg|gif|bmp|ogg|oga)(\))/', '('.$static.'/get.php?h='.$hash.'&t=$2&f=$4$5)', $string);
+       }
+       
+       return $string;
+}
+
+// The function to set the good translation to a JS file
+function setTranslation($string) {
+       return preg_replace('/_e\("([^\"\"]+)"\)/e', "'_e(\"'.addslashes(T_gettext(stripslashes('$1'))).'\")'", $string);
+}
+
+// The function to set the good locales
+function setLocales($string, $locale) {
+       // Generate the two JS array list
+       $available_list = availableLocales($locale);
+       $available_id = '';
+       $available_names = '';
+       
+       // Add the values to the arrays
+       foreach($available_list as $current_id => $current_name) {
+               $available_id .= '\''.$current_id.'\', ';
+               $available_names .= '\''.addslashes($current_name).'\', ';
+       }
+       
+       // Remove the last comma
+       $regex = '/(.+), $/';
+       $available_id = preg_replace($regex, '$1', $available_id);
+       $available_names = preg_replace($regex, '$1', $available_names);
+       
+       // Locales array
+       $array = array(
+                       'LOCALES_AVAILABLE_ID' => $available_id,
+                       'LOCALES_AVAILABLE_NAMES' => $available_names
+                     );
+       
+       // Apply it!
+       foreach($array as $array_key => $array_value)
+               $string = preg_replace('/(var '.$array_key.'(( )?=( )?)new Array\()(\);)/', '$1'.$array_value.'$5', $string);
+       
+       return $string;
+}
+
+// The function to set the good configuration to a JS file
+function setConfiguration($string, $locale, $version, $max_upload) {
+       // Special BOSH URL if BOSH proxy enabled
+       if(BOSHProxy())
+               $bosh_special = staticLocation().'php/bosh.php';
+       else
+               $bosh_special = HOST_BOSH;
+       
+       // Configuration array
+       $array = array(
+                       // xml:lang
+                       'XML_LANG'              => $locale,
+                       
+                       // Jappix parameters
+                       'JAPPIX_STATIC'         => staticLocation(),
+                       'JAPPIX_VERSION'        => $version,
+                       'JAPPIX_MAX_FILE_SIZE'  => $max_upload,
+                       'JAPPIX_MAX_UPLOAD'     => formatBytes($max_upload),
+                       
+                       // Main configuration
+                       'SERVICE_NAME'          => SERVICE_NAME,
+                       'SERVICE_DESC'          => SERVICE_DESC,
+                       'JAPPIX_RESOURCE'       => JAPPIX_RESOURCE,
+                       'LOCK_HOST'             => LOCK_HOST,
+                       'ANONYMOUS'             => ANONYMOUS,
+                       'REGISTRATION'          => REGISTRATION,
+                       'BOSH_PROXY'            => BOSH_PROXY,
+                       'MANAGER_LINK'          => MANAGER_LINK,
+                       'GROUPCHATS_JOIN'       => GROUPCHATS_JOIN,
+                       'ENCRYPTION'            => ENCRYPTION,
+                       'HTTPS_STORAGE'         => HTTPS_STORAGE,
+                       'HTTPS_FORCE'           => HTTPS_FORCE,
+                       'COMPRESSION'           => COMPRESSION,
+                       'MULTI_FILES'           => MULTI_FILES,
+                       'DEVELOPER'             => DEVELOPER,
+                       
+                       // Hosts configuration
+                       'HOST_MAIN'             => HOST_MAIN,
+                       'HOST_MUC'              => HOST_MUC,
+                       'HOST_PUBSUB'           => HOST_PUBSUB,
+                       'HOST_VJUD'             => HOST_VJUD,
+                       'HOST_ANONYMOUS'        => HOST_ANONYMOUS,
+                       'HOST_BOSH'             => $bosh_special,
+                       'HOST_BOSH_MAIN'        => HOST_BOSH_MAIN,
+                       'HOST_BOSH_MINI'        => HOST_BOSH_MINI,
+                       'HOST_STATIC'           => HOST_STATIC,
+                       'HOST_UPLOAD'           => HOST_UPLOAD
+                     );
+       
+       // Apply it!
+       foreach($array as $array_key => $array_value)
+               $string = preg_replace('/var '.$array_key.'(( )?=( )?)null;/', 'var '.$array_key.'$1\''.addslashes($array_value).'\';', $string);
+       
+       return $string;
+}
+
+// The function to set the logos
+function setLogos($string, $files) {
+       // Jappix Desktop home logo?
+       if(in_array('home.css', $files) && file_exists(JAPPIX_BASE.'/store/logos/desktop_home.png')) {
+               $string .=
+'#home .left .logo {
+       background-image: url(../store/logos/desktop_home.png) !important;
+       background-position: center center !important;
+}';
+       }
+       
+       // Jappix Desktop app logo?
+       if(in_array('tools.css', $files) && file_exists(JAPPIX_BASE.'/store/logos/desktop_app.png')) {
+               $string .=
+'#top-content .tools-logo {
+       background-image: url(../store/logos/desktop_app.png) !important;
+       background-position: center center !important;
+}';
+       }
+       
+       // Jappix Mobile logo?
+       if(in_array('mobile.css', $files) && file_exists(JAPPIX_BASE.'/store/logos/mobile.png')) {
+               $string .=
+'.header div {
+       background-image: url(../store/logos/mobile.png) !important;
+       background-position: center center !important;
+}';
+       }
+       
+       // Jappix Mini logo?
+       if(in_array('mini.css', $files) && file_exists(JAPPIX_BASE.'/store/logos/mini.png')) {
+               $string .=
+'#jappix_mini div.jm_actions a.jm_logo {
+       background-image: url(../store/logos/mini.png) !important;
+       background-position: center center !important;
+}';
+       }       
+       
+       return $string;
+}
+
+// The function to set the background
+function setBackground($string) {
+       // Get the default values
+       $array = defaultBackground();
+       
+       // Read the background configuration
+       $xml = readXML('conf', 'background');
+       
+       if($xml) {
+               $read = new SimpleXMLElement($xml);
+               
+               foreach($read->children() as $child) {
+                       // Any value?
+                       if($child)
+                               $array[$child->getName()] = $child;
+               }
+       }
+       
+       $css = '';
+       
+       // Generate the CSS code
+       switch($array['type']) {
+               // Image
+               case 'image':
+                       $css .= 
+       "\n".'  background-image: url(../store/backgrounds/'.urlencode($array['image_file']).');
+       background-repeat: '.$array['image_repeat'].';
+       background-position: '.$array['image_horizontal'].' '.$array['image_vertical'].';
+       background-color: '.$array['image_color'].';'
+                       ;
+                       
+                       // Add CSS code to adapt the image?
+                       if($array['image_adapt'] == 'on')
+                               $css .= 
+       '       background-attachment: fixed;
+       background-size: cover;
+       -moz-background-size: cover;
+       -webkit-background-size: cover;';
+                       
+                       $css .= "\n";
+                       
+                       break;
+               
+               // Color
+               case 'color':
+                       $css .= "\n".'  background-color: '.$array['color_color'].';'."\n";
+                       
+                       break;
+               
+               // Default: use the filtering regex
+               default:
+                       $css .= '$3';
+                       
+                       break;
+       }
+       
+       // Apply the replacement!
+       return preg_replace('/(\.body-images( )?\{)([^\{\}]+)(\})/i', '$1'.$css.'$4', $string);
+}
+
+?>
diff --git a/jappixmini/jappix/php/functions-manager.php b/jappixmini/jappix/php/functions-manager.php
new file mode 100644 (file)
index 0000000..471fcc2
--- /dev/null
@@ -0,0 +1,769 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the PHP functions for Jappix manager
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, Mathieui, olivierm, Vinilox
+Last revision: 15/01/12
+
+*/
+
+// The function to check an user is admin
+function isAdmin($user, $password) {
+       // Read the users.xml file
+       $array = getUsers();
+       
+       // No data?
+       if(empty($array))
+               return false;
+       
+       // Our user is set and valid?
+       if(isset($array[$user]) && ($array[$user] == $password))
+               return true;
+       
+       // Not authorized
+       return false;
+}
+
+// Checks if a file is a valid image
+function isImage($file) {
+       // This is an image
+       if(preg_match('/^(.+)(\.)(png|jpg|jpeg|gif|bmp)$/i', $file))
+               return true;
+       
+       return false;
+}
+
+// Puts a marker on the current opened manager tab
+function currentTab($current, $page) {
+       if($current == $page)
+               echo ' class="tab-active"';
+}
+
+// Checks all the storage folders are writable
+function storageWritable() {
+       // Read the directory content
+       $dir = JAPPIX_BASE.'/store/';
+       $scan = scandir($dir);
+       
+       // Writable marker
+       $writable = true;
+       
+       // Check that each folder is writable
+       foreach($scan as $current) {
+               // Current folder
+               $folder = $dir.$current;
+               
+               // A folder is not writable?
+               if(!preg_match('/^\.(.+)/', $current) && !is_writable($folder)) {
+                       // Try to change the folder rights
+                       chmod($folder, 0777);
+                       
+                       // Check it again!
+                       if(!is_writable($folder))
+                               $writable = false;
+               }
+       }
+       
+       return $writable;
+}
+
+// Removes a given directory (with all sub-elements)
+function removeDir($dir) {
+       // Can't open the dir
+       if(!$dh = @opendir($dir))
+               return;
+       
+       // Loop the current dir to remove its content
+       while(false !== ($obj = readdir($dh))) {
+               // Not a "real" directory
+               if(($obj == '.') || ($obj == '..'))
+                       continue;
+               
+               // Not a file, remove this dir
+               if(!@unlink($dir.'/'.$obj))
+                       removeDir($dir.'/'.$obj);
+       }
+       
+       // Close the dir and remove it!
+       closedir($dh);
+       @rmdir($dir);
+}
+
+// Copies a given directory (with all sub-elements)
+function copyDir($source, $destination) {
+       // This is a directory
+       if(is_dir($source)) {
+               // Create the target directory
+               @mkdir($destination);
+               $directory = dir($source);
+               
+               // Append the source directory content into the target one
+               while(FALSE !== ($readdirectory = $directory->read())) {
+                       if(($readdirectory == '.') || ($readdirectory == '..'))
+                               continue;
+                       
+                       $PathDir = $source.'/'.$readdirectory;
+                       
+                       // Recursive copy
+                       if(is_dir($PathDir)) {
+                               copyDir($PathDir, $destination.'/'.$readdirectory);
+                               
+                               continue;
+                       }
+                       
+                       copy($PathDir, $destination.'/'.$readdirectory);
+               }
+               
+               // Close the source directory
+               $directory->close();
+       }
+       
+       // This is a file
+       else
+               copy($source, $destination);
+}
+
+// Gets the total size of a directory
+function sizeDir($dir) {
+       $size = 0;
+       
+       foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $file)
+               $size += $file->getSize();
+       
+       return $size;
+}
+
+// Set the good unity for a size in bytes
+function numericToMonth($id) {
+       $array = array(
+                       1 => T_("January"),
+                       2 => T_("February"),
+                       3 => T_("March"),
+                       4 => T_("April"),
+                       5 => T_("May"),
+                       6 => T_("June"),
+                       7 => T_("July"),
+                       8 => T_("August"),
+                       9 => T_("September"),
+                       10 => T_("October"),
+                       11 => T_("November"),
+                       12 =>T_( "December")
+                     );
+       
+       return $array[$id];
+}
+
+// Extracts the version number with a version ID
+function versionNumber($id) {
+       // First, extract the number string from the [X]
+       $extract = preg_replace('/^(.+)\[(\S+)\]$/', '$2', $id);
+       $dev = false;
+       
+       // Second extract: ~ (when this is a special version, like ~dev)
+       if(strrpos($extract, '~') !== false) {
+               $dev = true;
+               $extract = preg_replace('/^([^~])~(.+)$/', '$1', $extract);
+       }
+       
+       // Convert [X.X.X] into a full number
+       $extract = preg_replace('/[^0-9]/', '', $extract);
+       
+       // Add missing items to [X.X.X]
+       $missing = 3 - strlen($extract.'');
+       if($missing > 0)
+               $extract = $extract.(str_repeat('0', $missing));
+       
+       // Allows updates for dev versions
+       if($dev)
+               $extract = $extract - 1;
+       
+       return intval($extract);
+}
+
+// Checks for new Jappix updates
+function newUpdates($force) {
+       // No need to check if developer mode
+       if(isDeveloper())
+               return false;
+       
+       $cache_path = JAPPIX_BASE.'/store/updates/version.xml';
+       
+       // No cache, obsolete one or refresh forced
+       if(!file_exists($cache_path) || (file_exists($cache_path) && (time() - (filemtime($cache_path)) >= 86400)) || $force) {
+               // Get the content
+               $last_version = read_url('http://codingteam.net/project/jappix/upload/briefcase/version.xml');
+               
+               // Write the content
+               file_put_contents($cache_path, $last_version);
+       }
+       
+       // Read from the cache
+       else
+               $last_version = file_get_contents($cache_path);
+       
+       // Parse the XML
+       $xml = @simplexml_load_string($last_version);
+       
+       // No data?
+       if($xml === FALSE)
+               return false;
+       
+       // Get the version numbers
+       $current_version = getVersion();
+       $last_version = $xml->id;
+       
+       // Check if we have the latest version
+       $current_version = versionNumber($current_version);
+       $last_version = versionNumber($last_version);
+       
+       if($current_version < $last_version)
+               return true;
+       
+       return false;
+}
+
+// Gets the Jappix update informations
+function updateInformations() {
+       // Get the XML file content
+       $data = file_get_contents(JAPPIX_BASE.'/store/updates/version.xml');
+       
+       // Transform the XML content into an array
+       $array = array();
+       
+       // No XML?
+       if(!$data)
+               return $array;
+       
+       $xml = new SimpleXMLElement($data);
+       
+       // Parse the XML to add it to the array
+       foreach($xml->children() as $this_child) {
+               // Get the node name
+               $current_name = $this_child->getName();
+               
+               // Push it to the array, with a basic HTML encoding
+               $array[$current_name] = str_replace('\n', '<br />', $this_child);
+       }
+       
+       // Return this array
+       return $array;
+}
+
+// Processes the Jappix update from an external package
+function processUpdate($url) {
+       // Archive path
+       $name = md5($url).'.zip';
+       $update_dir = $dir_base.'store/updates/';
+       $path = JAPPIX_BASE.'/store/updates/'.$name;
+       $extract_to = $update_dir.'jappix/';
+       $store_tree = JAPPIX_BASE.'/php/store-tree.php';
+       
+       // We must get the archive from the server
+       if(!file_exists($path)) {
+               echo('<p>» '.T_("Downloading package...").'</p>');
+               
+               // Open the packages
+               $local = fopen($path, 'w');
+               $remote = fopen($url, 'r');
+               
+               // Could not open a socket?!
+               if(!$remote) {
+                       echo('<p>» '.T_("Aborted: socket error!").'</p>');
+                       
+                       // Remove the broken local archive
+                       unlink($path);
+                       
+                       return false;
+               }
+               
+               // Read the file
+               while(!feof($remote)) {
+                       // Get the buffer
+                       $buffer = fread($remote, 1024);
+                       
+                       // Any error?
+                       if($buffer == 'Error.') {
+                               echo('<p>» '.T_("Aborted: buffer error!").'</p>');
+                               
+                               // Remove the broken local archive
+                               unlink($path);
+                               
+                               return false;
+                       }
+                       
+                       // Write the buffer to the file
+                       fwrite($local, $buffer);
+                       
+                       // Flush the current buffer
+                       ob_flush();
+                       flush();
+               }
+               
+               // Close the files
+               fclose($local);
+               fclose($remote);
+       }
+       
+       // Then, we extract the archive
+       echo('<p>» '.T_("Extracting package...").'</p>');
+       
+       try {
+               $zip = new ZipArchive;
+               $zip_open = $zip->open($path);
+               
+               if($zip_open === TRUE) {
+                       $zip->extractTo($update_dir);
+                       $zip->close();
+               }
+               
+               else {
+                       echo('<p>» '.T_("Aborted: could not extract the package!").'</p>');
+                       
+                       // Remove the broken source folder
+                       removeDir($to_remove);
+                       
+                       return false;
+               }
+       }
+       
+       // PHP does not provide Zip archives support
+       catch(Exception $e) {
+               echo('<p>» '.T_("Aborted: could not extract the package!").'</p>');
+               
+               // Remove the broken source folder
+               removeDir($to_remove);
+               
+               return false;
+       }
+       
+       // Remove the ./store dir from the source directory
+       removeDir($extract_to.'store/');
+       
+       // Then, we remove the Jappix system files
+       echo('<p>» '.T_("Removing current Jappix system files...").'</p>');
+       
+       // Open the general directory
+       $dir_base = JAPPIX_BASE.'/';
+       $scan = scandir($dir_base);
+       
+       // Filter the scan array
+       $scan = array_diff($scan, array('.', '..', '.svn', 'store'));
+       
+       // Check all the files are writable
+       foreach($scan as $scanned) {
+               // Element path
+               $scanned_current = $dir_base.$scanned;
+               
+               // Element not writable
+               if(!is_writable($scanned_current)) {
+                       // Try to change the element rights
+                       chmod($scanned_current, 0777);
+                       
+                       // Check it again!
+                       if(!is_writable($scanned_current)) {
+                               echo('<p>» '.T_("Aborted: everything is not writable!").'</p>');
+                               
+                               return false;
+                       }
+               }
+       }
+       
+       // Process the files deletion
+       foreach($scan as $current) {
+               $to_remove = $dir_base.$current;
+               
+               // Remove folders
+               if(is_dir($to_remove))
+                       removeDir($to_remove);
+               
+               // Remove files
+               else
+                       unlink($to_remove);
+       }
+       
+       // Move the extracted files to the base
+       copyDir($extract_to, $dir_base);
+       
+       // Remove the source directory
+       removeDir($extract_to);
+       
+       // Regenerates the store tree
+       if(file_exists($store_tree)) {
+               echo('<p>» '.T_("Regenerating storage folder tree...").'</p>');
+               
+               // Call the special regeneration script
+               include($store_tree);
+       }
+       
+       // Remove the version package
+       unlink($path);
+       
+       // The new version is now installed!
+       echo('<p>» '.T_("Jappix is now up to date!").'</p>');
+       
+       return true;
+}
+
+// Returns an array with the biggest share folders
+function shareStats() {
+       // Define some stuffs
+       $path = JAPPIX_BASE.'/store/share/';
+       $array = array();
+       
+       // Open the directory
+       $scan = scandir($path);
+       
+       // Loop the share files
+       foreach($scan as $current) {
+               if(is_dir($path.$current) && !preg_match('/^(\.(.+)?)$/i', $current))
+                       array_push($array, $current);
+       }
+       
+       return $array;
+}
+
+// Returns the largest share folders
+function largestShare($array, $number) {
+       // Define some stuffs
+       $path = JAPPIX_BASE.'/store/share/';
+       $size_array = array();
+       
+       // Push the results in an array
+       foreach($array as $current)
+               $size_array[$current] = sizeDir($path.$current);
+       
+       // Sort this array
+       arsort($size_array);
+       
+       // Select the first biggest values
+       $size_array = array_slice($size_array, 0, $number);
+       
+       return $size_array;
+}
+
+// Returns the others statistics array
+function otherStats() {
+       // Fill the array with the values
+       $others_stats = array(
+                               T_("Backgrounds") => sizeDir(JAPPIX_BASE.'/store/backgrounds/'),
+                               T_("Cache") => sizeDir(JAPPIX_BASE.'/store/cache/'),
+                               T_("Logs") => sizeDir(JAPPIX_BASE.'/store/logs/'),
+                               T_("Music") => sizeDir(JAPPIX_BASE.'/store/music/'),
+                               T_("Share") => sizeDir(JAPPIX_BASE.'/store/share/'),
+                               T_("Send") => sizeDir(JAPPIX_BASE.'/store/send/'),
+                               T_("Updates") => sizeDir(JAPPIX_BASE.'/store/updates/')
+                            );
+       
+       // Sort this array
+       arsort($others_stats);
+       
+       return $others_stats;
+}
+
+// Gets the array of the visits stats
+function getVisits() {
+       // New array
+       $array = array(
+                       'total' => 0,
+                       'daily' => 0,
+                       'weekly' => 0,
+                       'monthly' => 0,
+                       'yearly' => 0
+                     );
+       
+       // Read the data
+       $data = readXML('access', 'total');
+       
+       // Any data?
+       if($data) {
+               // Initialize the visits reading
+               $xml = new SimpleXMLElement($data);
+               
+               // Get the XML values
+               $array['total'] = intval($xml->total);
+               $array['stamp'] = intval($xml->stamp);
+               
+               // Get the age of the stats
+               $age = time() - $array['stamp'];
+               
+               // Generate the time-dependant values
+               $timed = array(
+                               'daily' => 86400,
+                               'weekly' => 604800,
+                               'monthly' => 2678400,
+                               'yearly' => 31536000
+                             );
+               
+               foreach($timed as $timed_key => $timed_value) {
+                       if($age >= $timed_value)
+                               $array[$timed_key] = intval($array['total'] / ($age / $timed[$timed_key])).'';
+                       else
+                               $array[$timed_key] = $array['total'].'';
+               }
+       }
+       
+       return $array;
+}
+
+// Gets the array of the monthly visits
+function getMonthlyVisits() {
+       // New array
+       $array = array();
+       
+       // Read the data
+       $data = readXML('access', 'months');
+       
+       // Get the XML file values
+       if($data) {
+               // Initialize the visits reading
+               $xml = new SimpleXMLElement($data);
+               
+               // Loop the visit elements
+               foreach($xml->children() as $child) {
+                       // Get the current month ID
+                       $current_id = intval(preg_replace('/month_([0-9]+)/i', '$1', $child->getName()));
+                       
+                       // Get the current month name
+                       $current_name = numericToMonth($current_id);
+                       
+                       // Push it!
+                       $array[$current_name] = intval($child);
+               }
+       }
+       
+       return $array;
+}
+
+// Purges the target folder content
+function purgeFolder($folder) {
+       // Array of the folders to purge
+       $array = array();
+       
+       // We must purge all the folders?
+       if($folder == 'everything')
+               array_push($array, 'cache', 'logs', 'send', 'updates');
+       else
+               array_push($array, $folder);
+       
+       // All right, now we can empty it!
+       foreach($array as $current_folder) {
+               // Scan the current directory
+               $directory = JAPPIX_BASE.'/store/'.$current_folder.'/';
+               $scan = scandir($directory);
+               $scan = array_diff($scan, array('.', '..', '.svn', 'index.html'));
+               
+               // Process the files deletion
+               foreach($scan as $current) {
+                       $remove_this = $directory.$current;
+                       
+                       // Remove folders
+                       if(is_dir($remove_this))
+                               removeDir($remove_this);
+                       
+                       // Remove files
+                       else
+                               unlink($remove_this);
+               }
+       }
+}
+
+// Returns folder browsing informations
+function browseFolder($folder, $mode) {
+       // Scan the target directory
+       $directory = JAPPIX_BASE.'/store/'.$folder;
+       $scan = scandir($directory);
+       $scan = array_diff($scan, array('.', '..', '.svn', 'index.html'));
+       $keep_get = keepGet('(s|b|k)', false);
+       
+       // Odd/even marker
+       $marker = 'odd';
+       
+       // Not in the root folder: show previous link
+       if(strpos($folder, '/') != false) {
+               // Filter the folder name
+               $previous_folder = substr($folder, 0, strrpos($folder, '/'));
+               
+               echo('<div class="one-browse previous manager-images"><a href="./?b='.$mode.'&s='.urlencode($previous_folder).$keep_get.'">'.T_("Previous").'</a></div>');
+       }
+       
+       // Empty or non-existing directory?
+       if(!count($scan) || !is_dir($directory)) {
+               echo('<div class="one-browse '.$marker.' alert manager-images">'.T_("The folder is empty.").'</div>');
+               
+               return false;
+       }
+       
+       // Echo the browsing HTML code
+       foreach($scan as $current) {
+               // Generate the item path$directory
+               $path = $directory.'/'.$current;
+               $file = $folder.'/'.$current;
+               
+               // Directory?
+               if(is_dir($path)) {
+                       $type = 'folder';
+                       $href = './?b='.$mode.'&s='.urlencode($file).$keep_get;
+                       $target = '';
+               }
+               
+               // File?
+               else {
+                       $type = getFileType(getFileExt($path));
+                       $href = $path;
+                       $target = ' target="_blank"';
+               }
+               
+               echo('<div class="one-browse '.$marker.' '.$type.' manager-images"><a href="'.$href.'"'.$target.'>'.htmlspecialchars($current).'</a><input type="checkbox" name="element_'.md5($file).'" value="'.htmlspecialchars($file).'" /></div>');
+               
+               // Change the marker
+               if($marker == 'odd')
+                       $marker = 'even';
+               else
+                       $marker = 'odd';
+       }
+       
+       return true;
+}
+
+// Removes selected elements (files/folders)
+function removeElements() {
+       // Initialize the match
+       $elements_removed = false;
+       $elements_remove = array();
+       
+       // Try to get the elements to remove
+       foreach($_POST as $post_key => $post_value) {
+               // Is a safe file?
+               if(preg_match('/^element_(.+)$/i', $post_key) && isSafe($post_value)) {
+                       // Update the marker
+                       $elements_removed = true;
+                       
+                       // Get the real path
+                       $post_element = JAPPIX_BASE.'/store/'.$post_value;
+                       
+                       // Remove the current element
+                       if(is_dir($post_element))
+                               removeDir($post_element);
+                       else if(file_exists($post_element))
+                               unlink($post_element);
+               }
+       }
+       
+       // Show a notification message
+       if($elements_removed)
+               echo('<p class="info smallspace success">'.T_("The selected elements have been removed.").'</p>');
+       else
+               echo('<p class="info smallspace fail">'.T_("You must select elements to remove!").'</p>');
+}
+
+// Returns users browsing informations
+function browseUsers() {
+       // Get the users
+       $array = getUsers();
+       
+       // Odd/even marker
+       $marker = 'odd';
+       
+       // Echo the browsing HTML code
+       foreach($array as $user => $password) {
+               // Filter the username
+               $user = htmlspecialchars($user);
+               
+               // Output the code
+               echo('<div class="one-browse '.$marker.' user manager-images"><span>'.$user.'</span><input type="checkbox" name="admin_'.md5($user).'" value="'.$user.'" /><div class="clear"></div></div>');
+               
+               // Change the marker
+               if($marker == 'odd')
+                       $marker = 'even';
+               else
+                       $marker = 'odd';
+       }
+}
+
+// Generates the logo form field
+function logoFormField($id, $name) {
+       if(file_exists(JAPPIX_BASE.'/store/logos/'.$name.'.png'))
+               echo '<span class="logo_links"><a class="remove manager-images" href="./?k='.urlencode($name).keepGet('k', false).'" title="'.T_("Remove this logo").'"></a><a class="view manager-images" href="./store/logos/'.$name.'.png" target="_blank" title="'.T_("View this logo").'"></a></span>';
+       else
+               echo '<input id="logo_own_'.$id.'_location" type="file" name="logo_own_'.$id.'_location" accept="image/*" />';
+       
+       echo "\n";
+}
+
+// Reads the background configuration
+function readBackground() {
+       // Read the background configuration XML
+       $background_data = readXML('conf', 'background');
+       
+       // Get the default values
+       $background_default = defaultBackground();
+       
+       // Stored data array
+       $background_conf = array();
+       
+       // Read the stored values
+       if($background_data) {
+               // Initialize the background configuration XML data
+               $background_xml = new SimpleXMLElement($background_data);
+               
+               // Loop the notice configuration elements
+               foreach($background_xml->children() as $background_child)
+                       $background_conf[$background_child->getName()] = $background_child;
+       }
+       
+       // Checks no value is missing in the stored configuration
+       foreach($background_default as $background_name => $background_value) {
+               if(!isset($background_conf[$background_name]) || empty($background_conf[$background_name]))
+                       $background_conf[$background_name] = $background_default[$background_name];
+       }
+       
+       return $background_conf;
+}
+
+// Writes the background configuration
+function writeBackground($array) {
+       // Generate the XML data
+       $xml = '';
+       
+       foreach($array as $key => $value)
+               $xml .= "\n".'  <'.$key.'>'.stripslashes(htmlspecialchars($value)).'</'.$key.'>';
+       
+       // Write this data
+       writeXML('conf', 'background', $xml);
+}
+
+// Generates a list of the available background images
+function getBackgrounds() {
+       // Initialize the result array
+       $array = array();
+       
+       // Scan the background directory
+       $scan = scandir(JAPPIX_BASE.'/store/backgrounds/');
+       
+       foreach($scan as $current) {
+               if(isImage($current))
+                       array_push($array, $current);
+       }
+       
+       return $array;
+}
+
+// Writes the notice configuration
+function writeNotice($type, $simple) {
+       // Generate the XML data
+       $xml = 
+       '<type>'.$type.'</type>
+       <notice>'.stripslashes(htmlspecialchars($simple)).'</notice>'
+       ;
+       
+       // Write this data
+       writeXML('conf', 'notice', $xml);
+}
+
+?>
diff --git a/jappixmini/jappix/php/functions.php b/jappixmini/jappix/php/functions.php
new file mode 100644 (file)
index 0000000..af73777
--- /dev/null
@@ -0,0 +1,1427 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the PHP functions for Jappix
+
+-------------------------------------------------
+
+License: AGPL
+Authors: Vanaryon, LinkMauve, Mathieui, olivierm
+Last revision: 16/01/12
+
+*/
+
+// The function to check if Jappix is already installed
+function isInstalled() {
+       if(!file_exists(JAPPIX_BASE.'/store/conf/installed.xml'))
+               return false;
+       
+       return true;
+}
+
+// The function to check if a static host is defined
+function hasStatic() {
+       if(HOST_STATIC && (HOST_STATIC != '.'))
+               return true;
+       
+       return false;
+}
+
+// The function to check if this is a static server
+function isStatic() {
+       if(hasStatic() && (parse_url(HOST_STATIC, PHP_URL_HOST) == $_SERVER['HTTP_HOST']))
+               return true;
+       
+       return false;
+}
+
+// The function to check if this is an upload server
+function isUpload() {
+       if(HOST_UPLOAD && (parse_url(HOST_UPLOAD, PHP_URL_HOST) == $_SERVER['HTTP_HOST']))
+               return true;
+       
+       return false;
+}
+
+// The function to get the users.xml file hashed name
+function usersConfName() {
+       $conf_dir = JAPPIX_BASE.'/store/conf';
+       
+       // No conf folder?
+       if(!is_dir($conf_dir))
+               return '';
+       
+       // Read the conf folder
+       $conf_scan = scandir($conf_dir.'/');
+       $conf_name = '';
+       
+       // Loop the XML files
+       foreach($conf_scan as $current) {
+               if(preg_match('/(.+)(\.users\.xml)($)/', $current)) {
+                       $conf_name = $current;
+                       
+                       break;
+               }
+       }
+       
+       // Return the users file name
+       return $conf_name;
+}
+
+// The function to write a XML file
+function writeXML($type, $xmlns, $xml) {
+       // Generate the file path
+       $conf_path = JAPPIX_BASE.'/store/'.$type.'/';
+       $conf_name = $xmlns.'.xml';
+       
+       // Secured stored file?
+       if(($type == 'conf') && ($xmlns == 'users')) {
+               // Get the secured file name
+               $conf_secured = usersConfName();
+               
+               // Does this file exist?
+               if($conf_secured)
+                       $conf_name = $conf_secured;
+               else
+                       $conf_name = hash('sha256', rand(1, 99999999).time()).'.users.xml';
+       }
+       
+       // Generate the file complete path
+       $conf_file = $conf_path.$conf_name;
+       
+       // Write the installed marker
+       $gen_xml = '<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:'.$type.':'.$xmlns.'">
+       '.trim($xml).'
+</jappix>';
+       
+       file_put_contents($conf_file, $gen_xml);
+       
+       return true;
+}
+
+// The function to read a XML file
+function readXML($type, $xmlns) {
+       // Generate the file path
+       $conf_path = JAPPIX_BASE.'/store/'.$type.'/';
+       $conf_name = $xmlns.'.xml';
+       
+       // Secured stored file?
+       if(($type == 'conf') && ($xmlns == 'users')) {
+               // Get the secured file name
+               $conf_secured = usersConfName();
+               
+               // Does this file exist?
+               if($conf_secured)
+                       $conf_name = $conf_secured;
+       }
+       
+       // Generate the file complete path
+       $conf_file = $conf_path.$conf_name;
+       
+       if(file_exists($conf_file))
+               return file_get_contents($conf_file);
+       
+       return false;
+}
+
+// The function to read remote URLs
+function read_url($url) {
+       // Any cURL?
+       if(function_exists('curl_init')) {
+               $ch = curl_init();
+               curl_setopt($ch, CURLOPT_URL, $url);
+               curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+               curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
+               $data = curl_exec($ch);
+               curl_close($ch);
+       }
+       
+       // Default method
+       else
+               $data = @file_get_contents($url);
+       
+       return $data;
+}
+
+// The function to get the Jappix app. current version
+function getVersion() {
+       $file = file_get_contents(JAPPIX_BASE.'/VERSION');
+       $version = trim($file);
+       
+       return $version;
+}
+
+// The function to detect the user's language
+function checkLanguage() {
+       // If the user defined a language
+       if(isset($_GET['l']) && !empty($_GET['l'])) {
+               // We define some stuffs
+               $defined_lang = strtolower($_GET['l']);
+               $lang_file = JAPPIX_BASE.'/lang/'.$defined_lang.'/LC_MESSAGES/main.mo';
+               
+               if($defined_lang == 'en')
+                       $lang_found = true;
+               else
+                       $lang_found = file_exists($lang_file);
+               
+               // We check if the asked translation exists
+               if($lang_found) {
+                       $lang = $defined_lang;
+                       
+                       // Write a cookie
+                       setcookie('jappix_locale', $lang, (time() + 31536000));
+                       
+                       return $lang;
+               }
+       }
+       
+       // No language has been defined, but a cookie is stored
+       if(isset($_COOKIE['jappix_locale'])) {
+               $check_cookie = $_COOKIE['jappix_locale'];
+               
+               // The cookie has a value, check this value
+               if($check_cookie && (file_exists(JAPPIX_BASE.'/lang/'.$check_cookie.'/LC_MESSAGES/main.mo') || ($check_cookie == 'en')))
+                       return $check_cookie;
+       }
+       
+       // No cookie defined (or an unsupported value), naturally, we check the browser language
+       if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
+               return 'en';
+       
+       // We get the language of the browser
+       $nav_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+       $check_en = strtolower($nav_langs[0]);
+       
+       // We check if this is not english
+       if($check_en == 'en')
+               return 'en';
+       
+       $order = array();
+       
+       foreach($nav_langs as $entry) {
+               $indice = explode('=', $entry);
+               $lang = strtolower(substr(trim($indice[0]), 0, 2));
+               
+               if(!isset($indice[1]) || !$indice[1])
+                       $indice = 1;
+               else
+                       $indice = $indice[1];
+               
+               $order[$lang] = $indice;
+       }
+       
+       arsort($order);
+       
+       foreach($order as $nav_lang => $val) {
+               $lang_found = file_exists(JAPPIX_BASE.'/lang/'.$nav_lang.'/LC_MESSAGES/main.mo');
+               
+               if($lang_found)
+                       return $nav_lang;
+       }
+       
+       // If Jappix doen't know that language, we include the english translation
+       return 'en';
+}
+
+// The function to convert a ISO language code to its full name
+function getLanguageName($code) {
+       $code = strtolower($code);
+       
+       $known = array(
+               'aa' => 'Afaraf',
+               'ab' => 'Аҧсуа',
+               'ae' => 'Avesta',
+               'af' => 'Afrikaans',
+               'ak' => 'Akan',
+               'am' => 'አማርኛ',
+               'an' => 'Aragonés',
+               'ar' => 'العربية',
+               'as' => 'অসমীয়া',
+               'av' => 'авар мацӀ',
+               'ay' => 'Aymar aru',
+               'az' => 'Azərbaycan dili',
+               'ba' => 'башҡорт теле',
+               'be' => 'Беларуская',
+               'bg' => 'български',
+               'bh' => 'भोजपुरी',
+               'bi' => 'Bislama',
+               'bm' => 'Bamanankan',
+               'bn' => 'বাংলা',
+               'bo' => 'བོད་ཡིག',
+               'br' => 'Brezhoneg',
+               'bs' => 'Bosanski jezik',
+               'ca' => 'Català',
+               'ce' => 'нохчийн мотт',
+               'ch' => 'Chamoru',
+               'co' => 'Corsu',
+               'cr' => 'ᓀᐦᐃᔭᐍᐏᐣ',
+               'cs' => 'Česky',
+               'cu' => 'Словѣньскъ',
+               'cv' => 'чӑваш чӗлхи',
+               'cy' => 'Cymraeg',
+               'da' => 'Dansk',
+               'de' => 'Deutsch',
+               'dv' => 'ދިވެހި',
+               'dz' => 'རྫོང་ཁ',
+               'ee' => 'Ɛʋɛgbɛ',
+               'el' => 'Ελληνικά',
+               'en' => 'English',
+               'eo' => 'Esperanto',
+               'es' => 'Español',
+               'et' => 'Eesti keel',
+               'eu' => 'Euskara',
+               'fa' => 'فارسی',
+               'ff' => 'Fulfulde',
+               'fi' => 'Suomen kieli',
+               'fj' => 'Vosa Vakaviti',
+               'fo' => 'Føroyskt',
+               'fr' => 'Français',
+               'fy' => 'Frysk',
+               'ga' => 'Gaeilge',
+               'gd' => 'Gàidhlig',
+               'gl' => 'Galego',
+               'gn' => 'Avañe\'ẽ',
+               'gu' => 'ગુજરાતી',
+               'gv' => 'Ghaelg',
+               'ha' => 'هَوُسَ',
+               'he' => 'עברית',
+               'hi' => 'हिन्दी',
+               'ho' => 'Hiri Motu',
+               'hr' => 'Hrvatski',
+               'ht' => 'Kreyòl ayisyen',
+               'hu' => 'Magyar',
+               'hy' => 'Հայերեն',
+               'hz' => 'Otjiherero',
+               'ia' => 'Interlingua',
+               'id' => 'Bahasa',
+               'ie' => 'Interlingue',
+               'ig' => 'Igbo',
+               'ii' => 'ꆇꉙ',
+               'ik' => 'Iñupiaq',
+               'io' => 'Ido',
+               'is' => 'Íslenska',
+               'it' => 'Italiano',
+               'iu' => 'ᐃᓄᒃᑎᑐᑦ',
+               'ja' => '日本語',
+               'jv' => 'Basa Jawa',
+               'ka' => 'ქართული',
+               'kg' => 'KiKongo',
+               'ki' => 'Gĩkũyũ',
+               'kj' => 'Kuanyama',
+               'kk' => 'Қазақ тілі',
+               'kl' => 'Kalaallisut',
+               'km' => 'ភាសាខ្មែរ',
+               'kn' => 'ಕನ್ನಡ',
+               'ko' => '한 국어',
+               'kr' => 'Kanuri',
+               'ks' => 'कश्मीरी',
+               'ku' => 'Kurdî',
+               'kv' => 'коми кыв',
+               'kw' => 'Kernewek',
+               'ky' => 'кыргыз тили',
+               'la' => 'Latine',
+               'lb' => 'Lëtzebuergesch',
+               'lg' => 'Luganda',
+               'li' => 'Limburgs',
+               'ln' => 'Lingála',
+               'lo' => 'ພາສາລາວ',
+               'lt' => 'Lietuvių kalba',
+               'lu' => 'cilubà',
+               'lv' => 'Latviešu valoda',
+               'mg' => 'Fiteny malagasy',
+               'mh' => 'Kajin M̧ajeļ',
+               'mi' => 'Te reo Māori',
+               'mk' => 'македонски јазик',
+               'ml' => 'മലയാളം',
+               'mn' => 'Монгол',
+               'mo' => 'лимба молдовеняскэ',
+               'mr' => 'मराठी',
+               'ms' => 'Bahasa Melayu',
+               'mt' => 'Malti',
+               'my' => 'ဗမာစာ',
+               'na' => 'Ekakairũ Naoero',
+               'nb' => 'Norsk bokmål',
+               'nd' => 'isiNdebele',
+               'ne' => 'नेपाली',
+               'ng' => 'Owambo',
+               'nl' => 'Nederlands',
+               'nn' => 'Norsk nynorsk',
+               'no' => 'Norsk',
+               'nr' => 'Ndébélé',
+               'nv' => 'Diné bizaad',
+               'ny' => 'ChiCheŵa',
+               'oc' => 'Occitan',
+               'oj' => 'ᐊᓂᔑᓈᐯᒧᐎᓐ',
+               'om' => 'Afaan Oromoo',
+               'or' => 'ଓଡ଼ିଆ',
+               'os' => 'Ирон æвзаг',
+               'pa' => 'ਪੰਜਾਬੀ',
+               'pi' => 'पािऴ',
+               'pl' => 'Polski',
+               'ps' => 'پښتو',
+               'pt' => 'Português',
+               'pt-br' => 'Brasileiro',
+               'qu' => 'Runa Simi',
+               'rm' => 'Rumantsch grischun',
+               'rn' => 'kiRundi',
+               'ro' => 'Română',
+               'ru' => 'Русский',
+               'rw' => 'Kinyarwanda',
+               'sa' => 'संस्कृतम्',
+               'sc' => 'sardu',
+               'sd' => 'सिन्धी',
+               'se' => 'Davvisámegiella',
+               'sg' => 'Yângâ tî sängö',
+               'sh' => 'Српскохрватски',
+               'si' => 'සිංහල',
+               'sk' => 'Slovenčina',
+               'sl' => 'Slovenščina',
+               'sm' => 'Gagana fa\'a Samoa',
+               'sn' => 'chiShona',
+               'so' => 'Soomaaliga',
+               'sq' => 'Shqip',
+               'sr' => 'српски језик',
+               'ss' => 'SiSwati',
+               'st' => 'seSotho',
+               'su' => 'Basa Sunda',
+               'sv' => 'Svenska',
+               'sw' => 'Kiswahili',
+               'ta' => 'தமிழ்',
+               'te' => 'తెలుగు',
+               'tg' => 'тоҷикӣ',
+               'th' => 'ไทย',
+               'ti' => 'ትግርኛ',
+               'tk' => 'Türkmen',
+               'tl' => 'Tagalog',
+               'tn' => 'seTswana',
+               'to' => 'faka Tonga',
+               'tr' => 'Türkçe',
+               'ts' => 'xiTsonga',
+               'tt' => 'татарча',
+               'tw' => 'Twi',
+               'ty' => 'Reo Mā`ohi',
+               'ug' => 'Uyƣurqə',
+               'uk' => 'українська',
+               'ur' => 'اردو',
+               'uz' => 'O\'zbek',
+               've' => 'tshiVenḓa',
+               'vi' => 'Tiếng Việt',
+               'vo' => 'Volapük',
+               'wa' => 'Walon',
+               'wo' => 'Wollof',
+               'xh' => 'isiXhosa',
+               'yi' => 'ייִדיש',
+               'yo' => 'Yorùbá',
+               'za' => 'Saɯ cueŋƅ',
+               'zh' => '中文',
+               'zu' => 'isiZulu'
+       );
+       
+       if(isset($known[$code]))
+               return $known[$code];
+       
+       return null;
+}
+
+// The function to know if a language is right-to-left
+function isRTL($code) {
+       switch($code) {
+               // RTL language
+               case 'ar':
+               case 'he':
+               case 'dv':
+               case 'ur':
+                       $is_rtl = true;
+                       
+                       break;
+               
+               // LTR language
+               default:
+                       $is_rtl = false;
+                       
+                       break;
+       }
+       
+       return $is_rtl;
+}
+
+// The function to set the good localized <html /> tag
+function htmlTag($locale) {
+       // Initialize the tag
+       $html = '<html xml:lang="'.$locale.'" lang="'.$locale.'" dir="';
+       
+       // Set the good text direction (TODO)
+       /* if(isRTL($locale))
+               $html .= 'rtl';
+       else
+               $html .= 'ltr'; */
+       
+       $html .= 'ltr';
+       
+       // Close the tag
+       $html .= '">';
+       
+       echo($html);
+}
+
+// The function which generates the available locales list
+function availableLocales($active_locale) {
+       // Initialize
+       $scan = scandir(JAPPIX_BASE.'/lang/');
+       $list = array();
+       
+       // Loop the available languages
+       foreach($scan as $current_id) {
+               // Get the current language name
+               $current_name = getLanguageName($current_id);
+               
+               // Not valid?
+               if(($current_id == $active_locale) || ($current_name == null))
+                       continue;
+               
+               // Add this to the list
+               $list[$current_id] = $current_name;
+       }
+       
+       return $list;
+}
+
+// The function which generates the language switcher hidden part
+function languageSwitcher($active_locale) {
+       // Initialize
+       $keep_get = keepGet('l', false);
+       $list = availableLocales($active_locale);
+       $html = '';
+       
+       // Generate the HTML code
+       foreach($list as $current_id => $current_name)
+               $html .= '<a href="./?l='.$current_id.$keep_get.'">'.htmlspecialchars($current_name).'</a>, ';
+       
+       // Output the HTML code
+       return $html;
+}
+
+// The function to generate a strong hash
+function genStrongHash($string) {
+       // Initialize
+       $i = 0;
+       
+       // Loop to generate a incredibly strong hash (can be a bit slow)
+       while($i < 10) {
+               $string = hash('sha256', $string);
+               
+               $i++;
+       }
+       
+       return $string;
+}
+
+// The function to generate the version hash
+function genHash($version) {
+       // Get the configuration files path
+       $conf_path = JAPPIX_BASE.'/store/conf/';
+       $conf_main = $conf_path.'main.xml';
+       $conf_hosts = $conf_path.'hosts.xml';
+       $conf_background = $conf_path.'background.xml';
+       $logos_dir = JAPPIX_BASE.'/store/logos/';
+       
+       // Get the hash of the main configuration file
+       if(file_exists($conf_main))
+               $hash_main = md5_file($conf_main);
+       else
+               $hash_main = '0';
+       
+       // Get the hash of the main configuration file
+       if(file_exists($conf_hosts))
+               $hash_hosts = md5_file($conf_hosts);
+       else
+               $hash_hosts = '0';
+       
+       // Get the hash of the background configuration file
+       if(file_exists($conf_background))
+               $hash_background = md5_file($conf_background);
+       else
+               $hash_background = '0';
+       
+       // Get the hash of the logos folder
+       $hash_logos = '';
+       
+       if(is_dir($logos_dir)) {
+               $logos_scan = scandir($logos_dir.'/');
+               
+               foreach($logos_scan as $logos_current) {
+                       if(getFileExt($logos_current) == 'png')
+                               $hash_logos .= md5_file($logos_dir.$logos_current);
+               }
+       }
+       
+       return md5($version.$hash_main.$hash_hosts.$hash_background.$hash_logos);
+}
+
+// The function to hide the error messages
+function hideErrors() {
+       // Hide errors if not developer
+       if(!isDeveloper()) {
+               ini_set('display_errors', 'off');
+               ini_set('error_reporting', 0);
+       }
+       
+       // Developers need to get error reports!
+       else {
+               ini_set('display_errors', 'on');
+               ini_set('error_reporting', E_ALL);
+       }
+}
+
+// The function to check BOSH proxy is enabled
+function BOSHProxy() {
+       if(BOSH_PROXY == 'on')
+               return true;
+       
+       return false;
+}
+
+// The function to check compression is enabled
+function hasCompression() {
+       if(COMPRESSION != 'off')
+               return true;
+       
+       return false;
+}
+
+// The function to check compression is available with the current client
+function canCompress() {
+       // Compression allowed by admin & browser?
+       if(hasCompression() && (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')))
+               return true;
+       
+       return false;
+}
+
+// The function to check whether to show manager link or not
+function showManagerLink() {
+       if(MANAGER_LINK != 'off')
+               return true;
+       
+       return false;
+}
+
+// The function to check HTTPS storage is allowed
+function httpsStorage() {
+       if(HTTPS_STORAGE == 'on')
+               return true;
+       
+       return false;
+}
+
+// The function to check HTTPS storage must be forced
+function httpsForce() {
+       if((HTTPS_FORCE == 'on') && sslCheck())
+               return true;
+       
+       return false;
+}
+
+// The function to check we use HTTPS
+function useHttps() {
+       if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on'))
+               return true;
+       
+       return false;
+}
+
+// The function to compress the output pages
+function compressThis() {
+       if(canCompress() && !isDeveloper())
+               ob_start('ob_gzhandler');
+}
+
+// The function to choose one file get with get.php or a liste of resources
+function multiFiles() {
+       if(MULTI_FILES == 'on')
+               return true;
+       
+       return false;
+}
+
+function getFiles($h, $l, $t, $g, $f) {
+       // Define the good path to the Get API
+       if(hasStatic())
+               $path_to = HOST_STATIC.'/';
+       else
+               $path_to = JAPPIX_BASE.'/';
+               
+       if(!multiFiles()) {
+               $values = array();
+               if ($h)
+                       $values[] = 'h='.$h;
+               if ($l)
+                       $values[] = 'l='.$l;
+               if ($t)
+                       $values[] = 't='.$t;
+               if ($g)
+                       $values[] = 'g='.$g;
+               if ($f)
+                       $values[] = 'f='.$f;
+               
+               return $path_to.'php/get.php?'.implode('&amp;', $values);
+       }
+       
+       if($g && !empty($g) && preg_match('/^(\S+)\.xml$/', $g) && preg_match('/^(css|js)$/', $t) && isSafe($g) && file_exists('xml/'.$g)) {
+               $xml_data = file_get_contents('xml/'.$g);
+               
+               // Any data?
+               if($xml_data) {
+                       $xml_read = new SimpleXMLElement($xml_data);
+                       $xml_parse = $xml_read->$t;
+                       
+                       // Files were added to the list before (with file var)?
+                       if($f)
+                               $f .= '~'.$xml_parse;
+                       else
+                               $f = $xml_parse;
+               }
+       }
+       
+       // Explode the f string
+       if(strpos($f, '~') != false)
+               $array = explode('~', $f);
+       else
+               $array = array($f);
+       
+       $a = array();
+       foreach($array as $file)
+               $a[] = $path_to.$t.'/'.$file;
+
+       if (count($a) == 1)
+               return $a[0];
+
+       return $a;
+}
+
+function echoGetFiles($h, $l, $t, $g, $f) {
+       if ($t == 'css')
+               $pattern = '<link rel="stylesheet" href="%s" type="text/css" media="all" />';
+       else if ($t == 'js')
+               $pattern = '<script type="text/javascript" src="%s"></script>';
+       
+       $files = getFiles($h, $l, $t, $g, $f);
+
+       if (is_string($files))
+               printf($pattern, $files);
+       else {
+               $c = count($files)-1;
+               for($i=0; $i<=$c; $i++) {
+                       if ($i)
+                               echo '  ';
+                       printf($pattern, $files[$i]);
+                       if ($i != $c)
+                               echo "\n";
+               }
+       }
+}
+
+// The function to check if anonymous mode is authorized
+function anonymousMode() {
+       if(isset($_GET['r']) && !empty($_GET['r']) && HOST_ANONYMOUS && (ANONYMOUS == 'on'))
+               return true;
+       else
+               return false;
+}
+
+// The function to quickly translate a string
+function _e($string) {
+       echo T_gettext($string);
+}
+
+// The function to check the encrypted mode
+function sslCheck() {
+       if(ENCRYPTION == 'on')
+               return true;
+       else
+               return false;
+}
+
+// The function to return the encrypted link
+function sslLink() {
+       // Using HTTPS?
+       if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on'))
+               $link = '<a class="home-images unencrypted" href="http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'">'.T_('Unencrypted').'</a>';
+       
+       // Using HTTP?
+       else
+               $link = '<a class="home-images encrypted" href="https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'">'.T_('Encrypted').'</a>';
+       
+       return $link;
+}
+
+// The function to get the Jappix static URL
+function staticURL() {
+       // Check for HTTPS
+       $protocol = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
+       
+       // Full URL
+       $url = $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
+       
+       return $url;
+}
+
+// The function to get the Jappix location (only from Get API!)
+function staticLocation() {
+       // Filter the URL
+       return preg_replace('/((.+)\/)php\/get\.php(\S)+$/', '$1', staticURL());
+}
+
+// The function to include a translation file
+function includeTranslation($locale, $domain) {
+       T_setlocale(LC_MESSAGES, $locale);
+       T_bindtextdomain($domain, JAPPIX_BASE.'/lang');
+       T_bind_textdomain_codeset($domain, 'UTF-8');
+       T_textdomain($domain);
+}
+
+// The function to check the cache presence
+function hasCache($hash) {
+       if(file_exists(JAPPIX_BASE.'/store/cache/'.$hash.'.cache'))
+               return true;
+       else
+               return false;
+}
+
+// The function to check if developer mode is enabled
+function isDeveloper() {
+       if(DEVELOPER == 'on')
+               return true;
+       else
+               return false;
+}
+
+// The function to get a file extension
+function getFileExt($name) {
+       return strtolower(preg_replace('/^(.+)(\.)([^\.]+)$/i', '$3', $name));
+}
+
+// The function to get a file type
+function getFileType($ext) {
+       switch($ext) {
+               // Images
+               case 'jpg':
+               case 'jpeg':
+               case 'png':
+               case 'bmp':
+               case 'gif':
+               case 'tif':
+               case 'svg':
+               case 'psp':
+               case 'xcf':
+                       $file_type = 'image';
+                       
+                       break;
+               
+               // Videos
+               case 'ogv':
+               case 'mkv':
+               case 'avi':
+               case 'mov':
+               case 'mp4':
+               case 'm4v':
+               case 'wmv':
+               case 'asf':
+               case 'mpg':
+               case 'mpeg':
+               case 'ogm':
+               case 'rmvb':
+               case 'rmv':
+               case 'qt':
+               case 'flv':
+               case 'ram':
+               case '3gp':
+               case 'avc':
+                       $file_type = 'video';
+                       
+                       break;
+               
+               // Sounds
+               case 'oga':
+               case 'ogg':
+               case 'mka':
+               case 'flac':
+               case 'mp3':
+               case 'wav':
+               case 'm4a':
+               case 'wma':
+               case 'rmab':
+               case 'rma':
+               case 'bwf':
+               case 'aiff':
+               case 'caf':
+               case 'cda':
+               case 'atrac':
+               case 'vqf':
+               case 'au':
+               case 'aac':
+               case 'm3u':
+               case 'mid':
+               case 'mp2':
+               case 'snd':
+               case 'voc':
+                       $file_type = 'audio';
+                       
+                       break;
+               
+               // Documents
+               case 'pdf':
+               case 'odt':
+               case 'ott':
+               case 'sxw':
+               case 'stw':
+               case 'ots':
+               case 'sxc':
+               case 'stc':
+               case 'sxi':
+               case 'sti':
+               case 'pot':
+               case 'odp':
+               case 'ods':
+               case 'doc':
+               case 'docx':
+               case 'docm':
+               case 'xls':
+               case 'xlsx':
+               case 'xlsm':
+               case 'xlt':
+               case 'ppt':
+               case 'pptx':
+               case 'pptm':
+               case 'pps':
+               case 'odg':
+               case 'otp':
+               case 'sxd':
+               case 'std':
+               case 'std':
+               case 'rtf':
+               case 'txt':
+               case 'htm':
+               case 'html':
+               case 'shtml':
+               case 'dhtml':
+               case 'mshtml':
+                       $file_type = 'document';
+                       
+                       break;
+               
+               // Packages
+               case 'tgz':
+               case 'gz':
+               case 'tar':
+               case 'ar':
+               case 'cbz':
+               case 'jar':
+               case 'tar.7z':
+               case 'tar.bz2':
+               case 'tar.gz':
+               case 'tar.lzma':
+               case 'tar.xz':
+               case 'zip':
+               case 'xz':
+               case 'rar':
+               case 'bz':
+               case 'deb':
+               case 'rpm':
+               case '7z':
+               case 'ace':
+               case 'cab':
+               case 'arj':
+               case 'msi':
+                       $file_type = 'package';
+                       
+                       break;
+               
+               // Others
+               default:
+                       $file_type = 'other';
+                       
+                       break;
+       }
+       
+       return $file_type;
+}
+
+// The function to get the MIME type of a file
+function getFileMIME($path) {
+       $finfo = finfo_open(FILEINFO_MIME_TYPE);
+       $cmime = finfo_file($finfo, $path);
+       finfo_close($finfo);
+       
+       return $cmime;
+}
+
+// The function to keep the current GET vars
+function keepGet($current, $no_get) {
+       // Get the HTTP GET vars
+       $request = $_SERVER['REQUEST_URI'];
+       
+       if(strrpos($request, '?') === false)
+               $get = '';
+       
+       else {
+               $uri = explode('?', $request);
+               $get = $uri[1];
+       }
+       
+       // Remove the items we don't want here
+       $proper = str_replace('&', '&amp;', $get);
+       $proper = preg_replace('/((^)|(&amp;))(('.$current.'=)([^&]+))/i', '', $proper);
+       
+       // Nothing at the end?
+       if(!$proper)
+               return '';
+       
+       // We have no defined GET var
+       if($no_get) {
+               // Remove the first "&" if it appears
+               if(preg_match('/^(&(amp;)?)/i', $proper))
+                       $proper = preg_replace('/^(&(amp;)?)/i', '', $proper);
+               
+               // Add the first "?"
+               $proper = '?'.$proper;
+       }
+       
+       // Add a first "&" if there is no one and no defined GET var
+       else if(!$no_get && (substr($proper, 0, 1) != '&') && (substr($proper, 0, 5) != '&amp;'))
+               $proper = '&amp;'.$proper;
+       
+       return $proper;
+}
+
+// Escapes regex special characters for in-regex usage
+function escapeRegex($string) {
+       return preg_replace('/[-[\]{}()*+?.,\\^$|#]/', '\\$&', $string);
+}
+
+// Generates the security HTML code
+function securityHTML() {
+       return '<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <title>Jappix - Forbidden</title>
+</head>
+
+<body>
+       <h1>Forbidden</h1>
+       <h4>This is a private folder</h4>
+</body>
+
+</html>';
+}
+
+// Checks if a relative server path is safe
+function isSafe($path) {
+       // Mhh, someone is about to nasty stuffs (previous folder, or executable scripts)
+       if(preg_match('/\.\.\//', $path) || preg_match('/index\.html?$/', $path) || preg_match('/(\.)((php([0-9]+)?)|(aspx?)|(cgi)|(rb)|(py)|(pl)|(jsp)|(ssjs)|(lasso)|(dna)|(tpl)|(smx)|(cfm))$/i', $path))
+               return false;
+       
+       return true;
+}
+
+// Set the good unity for a size in bytes
+function formatBytes($bytes, $precision = 2) {
+       $units = array('B', 'KB', 'MB', 'GB', 'TB');
+       
+       $bytes = max($bytes, 0);
+       $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
+       $pow = min($pow, count($units) - 1);
+       
+       $bytes /= pow(1024, $pow);
+       
+       return round($bytes, $precision) . ' ' . $units[$pow];
+}
+
+// Converts a human-readable bytes value to a computer one
+function humanToBytes($string) {
+       // Values array
+       $values = array(
+                       'K' => '000',
+                       'M' => '000000',
+                       'G' => '000000000',
+                       'T' => '000000000000',
+                       'P' => '000000000000000',
+                       'E' => '000000000000000000',
+                       'Z' => '000000000000000000000',
+                       'Y' => '000000000000000000000000'
+                      );
+       
+       // Filter the string
+       foreach($values as $key => $zero)
+               $string = str_replace($key, $zero, $string);
+       
+       // Converts the string into an integer
+       $string = intval($string);
+       
+       return $string;
+}
+
+// Get the maximum file upload size
+function uploadMaxSize() {
+       // Not allowed to upload files?
+       if(ini_get('file_uploads') != 1)
+               return 0;
+       
+       // Upload maximum file size
+       $upload = humanToBytes(ini_get('upload_max_filesize'));
+       
+       // POST maximum size
+       $post = humanToBytes(ini_get('post_max_size'));
+       
+       // Return the lowest value
+       if($upload <= $post)
+               return $upload;
+       
+       return $post;
+}
+
+// Normalizes special chars
+function normalizeChars($string) {
+       $table = array(
+               'Š'=>'S', 'š'=>'s', 'Đ'=>'Dj', 'đ'=>'dj', 'Ž'=>'Z', 'ž'=>'z', 'Č'=>'C', 'č'=>'c', 'Ć'=>'C', 'ć'=>'c',
+               'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
+               'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O',
+               'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss',
+               'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e',
+               'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o',
+               'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b',
+               'ÿ'=>'y', 'Ŕ'=>'R', 'ŕ'=>'r'
+       );
+       
+       return strtr($string, $table);
+}
+
+// Filters the XML special chars for the SVG drawer
+function filterSpecialXML($string) {
+       // Strange thing: when $string = 'Mises à jour' -> bug! but 'Mise à jour' -> ok!
+       $string = normalizeChars($string);
+       
+       // Encodes with HTML special chars
+       $string = htmlspecialchars($string);
+       
+       return $string;
+}
+
+// Writes the current visit in the total file
+function writeTotalVisit() {
+       // Get the current time stamp
+       $stamp = time();
+       
+       // Initialize the defaults
+       $array = array(
+                       'total' => 0,
+                       'stamp' => $stamp
+                     );
+       
+       // Try to read the saved data
+       $total_data = readXML('access', 'total');
+       
+       // Get the XML file values
+       if($total_data) {
+               // Initialize the visits reading
+               $read_xml = new SimpleXMLElement($total_data);
+               
+               // Loop the visit elements
+               foreach($read_xml->children() as $current_child)
+                       $array[$current_child->getName()] = intval($current_child);
+       }
+       
+       // Increment the total number of visits
+       $array['total']++;
+       
+       // Generate the new XML data
+       $total_xml = 
+       '<total>'.$array['total'].'</total>
+       <stamp>'.$array['stamp'].'</stamp>'
+       ;
+       
+       // Re-write the new values
+       writeXML('access', 'total', $total_xml);
+}
+
+// Writes the current visit in the months file
+function writeMonthsVisit() {
+       // Get the current month
+       $month = intval(date('m'));
+       
+       // Define the stats array
+       $array = array();
+       
+       // January to August period
+       if($month <= 8) {
+               for($i = 1; $i <= 8; $i++)
+                       $array['month_'.$i] = 0;
+       }
+       
+       // August to September period
+       else {
+               $i = 8;
+               $j = 1;
+               
+               while($j <= 3) {
+                       // Last year months
+                       if(($i >= 8) && ($i <= 12))
+                               $array['month_'.$i++] = 0;
+                       
+                       // First year months
+                       else
+                               $array['month_'.$j++] = 0;
+               }
+       }
+       
+       // Try to read the saved data
+       $months_data = readXML('access', 'months');
+       
+       // Get the XML file values
+       if($months_data) {
+               // Initialize the visits reading
+               $read_xml = new SimpleXMLElement($months_data);
+               
+               // Loop the visit elements
+               foreach($read_xml->children() as $current_child) {
+                       $current_month = $current_child->getName();
+                       
+                       // Parse the current month id
+                       $current_id = intval(preg_replace('/month_([0-9]+)/i', '$1', $current_month));
+                       
+                       // Is this month still valid?
+                       if((($month <= 8) && ($current_id <= $month)) || (($month >= 8) && ($current_id >= 8) && ($current_id <= $month)))
+                               $array[$current_month] = intval($current_child);
+               }
+       }
+       
+       // Increment the current month value
+       $array['month_'.$month]++;
+       
+       // Generate the new XML data
+       $months_xml = '';
+       
+       foreach($array as $array_key => $array_value)
+               $months_xml .= "\n".'   <'.$array_key.'>'.$array_value.'</'.$array_key.'>';
+       
+       // Re-write the new values
+       writeXML('access', 'months', $months_xml);
+}
+
+// Writes the current visit to the storage file
+function writeVisit() {
+       // Write total visits
+       writeTotalVisit();
+       
+       // Write months visits
+       writeMonthsVisit();
+}
+
+// Returns the default background array
+function defaultBackground() {
+       // Define the default values
+       $background_default = array(
+                               'type' => 'default',
+                               'image_file' => '',
+                               'image_repeat' => 'repeat-x',
+                               'image_horizontal' => 'center',
+                               'image_vertical' => 'top',
+                               'image_adapt' => 'off',
+                               'image_color' => '#cae1e9',
+                               'color_color' => '#cae1e9'
+                             );
+       
+       return $background_default;
+}
+
+// Reads the notice configuration
+function readNotice() {
+       // Read the notice configuration XML
+       $notice_data = readXML('conf', 'notice');
+       
+       // Define the default values
+       $notice_default = array(
+                               'type' => 'none',
+                               'notice' => ''
+                         );
+       
+       // Stored data array
+       $notice_conf = array();
+       
+       // Read the stored values
+       if($notice_data) {
+               // Initialize the notice configuration XML data
+               $notice_xml = new SimpleXMLElement($notice_data);
+               
+               // Loop the notice configuration elements
+               foreach($notice_xml->children() as $notice_child)
+                       $notice_conf[$notice_child->getName()] = utf8_decode($notice_child);
+       }
+       
+       // Checks no value is missing in the stored configuration
+       foreach($notice_default as $notice_name => $notice_value) {
+               if(!isset($notice_conf[$notice_name]) || empty($notice_conf[$notice_name]))
+                       $notice_conf[$notice_name] = $notice_default[$notice_name];
+       }
+       
+       return $notice_conf;
+}
+
+// The function to get the admin users
+function getUsers() {
+       // Try to read the XML file
+       $data = readXML('conf', 'users');
+       $array = array();
+       
+       // Any data?
+       if($data) {
+               $read = new SimpleXMLElement($data);
+               
+               // Check the submitted user exists
+               foreach($read->children() as $child) {
+                       // Get the node attributes
+                       $attributes = $child->attributes();
+                       
+                       // Push the attributes to the global array (converted into strings)
+                       $array[$attributes['name'].''] = $attributes['password'].'';
+               }
+       }
+       
+       return $array;
+}
+
+// Manages users
+function manageUsers($action, $array) {
+       // Try to read the old XML file
+       $users_array = getUsers();
+       
+       // What must we do?
+       switch($action) {
+               // Add some users
+               case 'add':
+                       foreach($array as $array_user => $array_password)
+                               $users_array[$array_user] = genStrongHash($array_password);
+                       
+                       break;
+               
+               // Remove some users
+               case 'remove':
+                       foreach($array as $array_user) {
+                               // Not the last user?
+                               if(count($users_array) > 1)
+                                       unset($users_array[$array_user]);
+                       }
+                       
+                       break;
+       }
+       
+       // Regenerate the XML
+       $users_xml = '';
+       
+       foreach($users_array as $users_name => $users_password)
+               $users_xml .= "\n".'    <user name="'.stripslashes(htmlspecialchars($users_name)).'" password="'.stripslashes($users_password).'" />';
+       
+       // Write the main configuration
+       writeXML('conf', 'users', $users_xml);
+}
+
+// Resize an image with GD
+function resizeImage($path, $ext, $width, $height) {
+       // No GD?
+       if(!function_exists('gd_info'))
+               return false;
+       
+       try {
+               // Initialize GD
+               switch($ext) {
+                       case 'png':
+                               $img_resize = imagecreatefrompng($path);
+                               
+                               break;
+                       
+                       case 'gif':
+                               $img_resize = imagecreatefromgif($path);
+                               
+                               break;
+                       
+                       default:
+                               $img_resize = imagecreatefromjpeg($path);
+               }
+               
+               // Get the image size
+               $img_size = getimagesize($path);
+               $img_width = $img_size[0];
+               $img_height = $img_size[1];
+       
+               // Necessary to change the image width
+               if($img_width > $width && ($img_width > $img_height)) {
+                       // Process the new sizes
+                       $new_width = $width;
+                       $img_process = (($new_width * 100) / $img_width);
+                       $new_height = (($img_height * $img_process) / 100);
+               }
+       
+               // Necessary to change the image height
+               else if($img_height > $height && ($img_width < $img_height)) {
+                       // Process the new sizes
+                       $new_height = $height;
+                       $img_process = (($new_height * 100) / $img_height);
+                       $new_width = (($img_width * $img_process) / 100);
+               }
+       
+               // Else, just use the old sizes
+               else {
+                       $new_width = $img_width;
+                       $new_height = $img_height;
+               }
+       
+               // Create the new image
+               $new_img = imagecreatetruecolor($new_width, $new_height);
+               
+               // Must keep alpha pixels?
+               if(($ext == 'png') || ($ext == 'gif')){
+                       imagealphablending($new_img, false);
+                       imagesavealpha($new_img, true);
+                       
+                       // Set transparent pixels
+                       $transparent = imagecolorallocatealpha($new_img, 255, 255, 255, 127);
+                       imagefilledrectangle($new_img, 0, 0, $new_width, $new_height, $transparent);
+               }
+               
+               // Copy the new image
+               imagecopyresampled($new_img, $img_resize, 0, 0, 0, 0, $new_width, $new_height, $img_size[0], $img_size[1]);
+       
+               // Destroy the old data
+               imagedestroy($img_resize);
+               unlink($path);
+       
+               // Write the new image
+               switch($ext) {
+                       case 'png':
+                               imagepng($new_img, $path);
+                               
+                               break;
+                       
+                       case 'gif':
+                               imagegif($new_img, $path);
+                               
+                               break;
+                       
+                       default:
+                               imagejpeg($new_img, $path, 85);
+               }
+               
+               return true;
+       }
+       
+       catch(Exception $e) {
+               return false;
+       }
+}
+
+?>
diff --git a/jappixmini/jappix/php/generate-chat.php b/jappixmini/jappix/php/generate-chat.php
new file mode 100644 (file)
index 0000000..19c8e71
--- /dev/null
@@ -0,0 +1,235 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the PHP script used to generate a chat log
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// Create the HTML file to be downloaded
+if(isset($_POST['content']) && isset($_POST['xid']) && !empty($_POST['xid']) && isset($_POST['nick']) && !empty($_POST['nick']) && isset($_POST['avatar']) && !empty($_POST['avatar']) && isset($_POST['date']) && !empty($_POST['date']) && isset($_POST['type']) && !empty($_POST['type'])) {
+       // Get the POST vars
+       $original = $_POST['content'];
+       $xid = $_POST['xid'];
+       $nick = $_POST['nick'];
+       $avatar = $_POST['avatar'];
+       $date = $_POST['date'];
+       $type = $_POST['type'];
+       
+       // Generate the XID link
+       $xid_link = 'xmpp:'.$xid;
+       
+       if($type == 'groupchat')
+               $xid_link .= '?join';
+       
+       // Generates the avatar code
+       if($avatar != 'none')
+               $avatar = '<div class="avatar-container">'.$avatar.'</div>';
+       else
+               $avatar = '';
+       
+       // Generates an human-readable date
+       $date = explode('T', $date);
+       $date = explode('-', $date[0]);
+       $date = $date[2].'/'.$date[1].'/'.$date[0];
+       
+       // Generate some values
+       $content_dir = '../store/logs/';
+       $filename = 'chat_log-'.md5($xid.time());
+       $filepath = $content_dir.$filename.'.html';
+       
+       // Generate Jappix logo Base64 code
+       $logo = base64_encode(file_get_contents(JAPPIX_BASE.'/img/sprites/logs.png'));
+       
+       // Create the HTML code
+       $new_text_inter = 
+'<!DOCTYPE html>
+<html> 
+
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+       <title>'.$nick.' ('.$xid.')</title>
+       <style type="text/css">
+               * {
+                       margin: 0;
+                       padding: 0;
+               }
+               
+               body {
+                       background-color: #424242;
+                       font-family : Verdana, Arial, Helvetica, sans-serif;
+                       font-size: 0.8em;
+                       text-shadow: 0 0 5px white;
+                       color: white;
+                       margin: 8px;
+                       padding: 8px 12px;
+               }
+               
+               a {
+                       color: white;
+               }
+               
+               #head {
+               
+               }
+               
+               #head .avatar-container {
+                       text-align: center;
+                       float: left;
+                       height: 70px;
+                       width: 70px;
+                       margin-right: 18px;
+               }
+               
+               #head .avatar {
+                       max-height: 70px;
+                       max-width: 70px;
+               }
+               
+               #head h1 {
+                       font-size: 2.2em;
+                       margin: 0;
+                       text-shadow: 1px 1px 1px black;
+               }
+               
+               #head h3 {
+                       font-size: 0.95em;
+                       margin: 0;
+               }
+               
+               #head h5 {
+                       font-size: 0.9em;
+                       margin: 8px 0 16px 0;
+               }
+               
+               #head h3,
+               #head h5 {
+                       text-shadow: 0 0 1px black;
+               }
+               
+               #head a.logo {
+                       position: absolute;
+                       top: 16px;
+                       right: 20px;
+               }
+               
+               #content {
+                       background-color: #e8f1f3;
+                       color: black;
+                       padding: 14px 18px;
+                       border-radius: 4px;
+                       clear: both;
+                       -moz-border-radius: 4px;
+                       -webkit-border-radius: 4px;
+                       box-shadow: 0 0 20px #202020;
+                       -moz-box-shadow: 0 0 20px #202020;
+                       -webkit-box-shadow: 0 0 20px #202020;
+               }
+               
+               #content a {
+                       color: black;
+               }
+               
+               #content .one-group {
+                       border-bottom: 1px dotted #d0d0d0;
+                       padding-bottom: 8px;
+                       margin-bottom: 10px;
+               }
+               
+               #content .one-group b.name {
+                       display: block;
+                       margin-bottom: 4px;
+               }
+               
+               #content .one-group b.name.me {
+                       color: #123a5c;
+               }
+               
+               #content .one-group b.name.him {
+                       color: #801e1e;
+               }
+               
+               #content .one-group span.date {
+                       float: right;
+                       font-size: 0.9em;
+               }
+               
+               #content .user-message {
+                       margin-bottom: 3px;
+               }
+               
+               #content .system-message {
+                       color: #053805;
+                       margin-bottom: 3px;
+                       padding-left: 0 !important;
+               }
+               
+               #content .system-message a {
+                       color: #053805;
+               }
+               
+               .hidden {
+                       display: none !important;
+               }
+       </style>
+</head>
+
+<body>
+       <div id="head">
+               '.$avatar.'
+               
+               <h1>'.$nick.'</h1>
+               <h3><a href="'.$xid_link.'">'.$xid.'</a></h3>
+               <h5>'.$date.'</h5>
+               
+               <a class="logo" href="https://project.jappix.com/" target="_blank">
+                       <img src="data:image/png;base64,'.$logo.'" alt="" />
+               </a>
+       </div>
+       
+       <div id="content">
+               '.$original.'
+       </div>
+</body>
+</html>'
+;
+       
+       $new_text = stripslashes($new_text_inter);
+       
+       // Write the code into a file
+       file_put_contents($filepath, $new_text);
+       
+       // Security: remove the file and stop the script if too bit (+6MiB)
+       if(filesize($filepath) > 6000000) {
+               unlink($filepath);
+               exit;
+       }
+       
+       // Return to the user the generated file ID
+       exit($filename);
+}
+
+?>
diff --git a/jappixmini/jappix/php/geolocation.php b/jappixmini/jappix/php/geolocation.php
new file mode 100644 (file)
index 0000000..acfdedb
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix geolocation script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/01/12
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// If valid data was sent
+if((isset($_GET['latitude']) && !empty($_GET['latitude'])) && (isset($_GET['longitude']) && !empty($_GET['longitude'])) && (isset($_GET['language']) && !empty($_GET['language']))) {
+       // Set a XML header
+       header('Content-Type: text/xml; charset=utf-8');
+       
+       // Get the XML content
+       $xml = read_url('http://maps.googleapis.com/maps/api/geocode/xml?latlng='.urlencode($_GET['latitude']).','.urlencode($_GET['longitude']).'&language='.urlencode($_GET['language']).'&sensor=true');
+       
+       exit($xml);
+}
+
+?>
diff --git a/jappixmini/jappix/php/get-store.php b/jappixmini/jappix/php/get-store.php
new file mode 100644 (file)
index 0000000..ce754b1
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the store configuration GET handler (manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Purge requested
+if(isset($_GET['p']) && preg_match('/^((everything)|(cache)|(logs)|(send)|(updates))$/', $_GET['p'])) {
+       purgeFolder($_GET['p']);
+?>
+       
+       <p class="info smallspace success"><?php _e("The storage folder you wanted to clean is now empty!"); ?></p>
+
+<?php }
+
+// Folder view?
+if(isset($_GET['b']) && isset($_GET['s'])) {
+       if($_GET['b'] == 'share')
+               $share_folder = urldecode($_GET['s']);
+       else if($_GET['b'] == 'music')
+               $music_folder = urldecode($_GET['s']);
+}
+
+?>
diff --git a/jappixmini/jappix/php/get.php b/jappixmini/jappix/php/get.php
new file mode 100644 (file)
index 0000000..f5078a7
--- /dev/null
@@ -0,0 +1,340 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the file get script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 03/12/11
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// We get the needed files
+require_once('./functions.php');
+require_once('./functions-get.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Hide PHP errors
+hideErrors();
+
+// Get some parameters
+$is_developer = isDeveloper();
+$has_compression = hasCompression();
+
+if($is_developer) {
+       header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
+       header('Cache-Control: no-store, no-cache, must-revalidate');
+       header('Cache-Control: post-check=0, pre-check=0', false);
+       header('Pragma: no-cache');
+}
+
+// Else, we put a far away cache date (1 year)
+else {
+       $expires = 31536000;
+       header('Pragma: public');
+       header('Cache-Control: maxage='.$expires);
+       header('Expires: '.gmdate('D, d M Y H:i:s', (time() + $expires)).' GMT');
+}
+
+// Initialize the vars
+$type = '';
+$file = '';
+
+// Read the type var
+if(isset($_GET['t']) && !empty($_GET['t']) && preg_match('/^(css|js|img|snd|store)$/', $_GET['t']))
+       $type = $_GET['t'];
+
+// Read the files var
+if(isset($_GET['f']) && !empty($_GET['f']) && isSafe($_GET['f']))
+       $file = $_GET['f'];
+
+// Read the group var (only for text files)
+if(isset($_GET['g']) && !empty($_GET['g']) && preg_match('/^(\S+)\.xml$/', $_GET['g']) && preg_match('/^(css|js)$/', $type) && isSafe($_GET['g']) && file_exists('../xml/'.$_GET['g'])) {
+       $xml_data = file_get_contents('../xml/'.$_GET['g']);
+       
+       // Any data?
+       if($xml_data) {
+               $xml_read = new SimpleXMLElement($xml_data);
+               $xml_parse = $xml_read->$type;
+               
+               // Files were added to the list before (with file var)?
+               if($file)
+                       $file .= '~'.$xml_parse;
+               else
+                       $file = $xml_parse;
+       }
+}
+
+// We check if the data was submitted
+if($file && $type) {
+       // We define some stuffs
+       $dir = '../'.$type.'/';
+       $path = $dir.$file;
+       
+       // Define the real type if this is a "store" file
+       if($type == 'store') {
+               // Extract the file extension
+               switch(getFileExt($file)) {
+                       // CSS file
+                       case 'css':
+                               $type = 'css';
+                               
+                               break;
+                       
+                       // JS file
+                       case 'js':
+                               $type = 'js';
+                               
+                               break;
+                       
+                       // Audio file
+                       case 'ogg':
+                       case 'oga':
+                               $type = 'snd';
+                               
+                               break;
+                       
+                       // Image file
+                       case 'png':
+                       case 'jpg':
+                       case 'jpeg':
+                       case 'gif':
+                       case 'bmp':
+                               $type = 'img';
+                               
+                               break;
+               }
+       }
+       
+       // JS and CSS special stuffs
+       if(($type == 'css') || ($type == 'js')) {
+               // Compression var
+               if($has_compression)
+                       $cache_encoding = 'deflate';
+               else
+                       $cache_encoding = 'plain';
+               
+               // Get the vars
+               $version = getVersion();
+               $hash = genHash($version);
+               $cache_hash = md5($path.$hash.staticLocation()).'_'.$cache_encoding;
+               
+               // Check if the browser supports DEFLATE
+               $deflate_support = false;
+               
+               if(isset($_SERVER['HTTP_ACCEPT_ENCODING']) && substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && hasCompression() && !$is_developer)
+                       $deflate_support = true;
+               
+               // Internationalization
+               if($type == 'js') {
+                       if(isset($_GET['l']) && !empty($_GET['l']) && !preg_match('/\.\.\//', $_GET['l']) && is_dir('../lang/'.$_GET['l']))
+                               $locale = $_GET['l'];
+                       else
+                               $locale = 'en';
+               }
+               
+               else
+                       $locale = '';
+               
+               // Define the cache lang name
+               if($locale)
+                       $cache_lang = $cache_hash.'_'.$locale;
+               else
+                       $cache_lang = $cache_hash;
+       }
+       
+       // Explode the file string
+       if(strpos($file, '~') != false)
+               $array = explode('~', $file);
+       else
+               $array = array($file);
+       
+       // Define the reading vars
+       $continue = true;
+       $loop_files = true;
+       
+       // Check the cache exists for text files (avoid the heavy file_exists loop!)
+       if(!$is_developer && (($type == 'css') || ($type == 'js')) && hasCache($cache_lang))
+               $loop_files = false;
+       
+       // Check if the all the file(s) exist(s)
+       if($loop_files) {
+               foreach($array as $current) {
+                       // Stop the loop if a file is missing
+                       if(!file_exists($dir.$current)) {
+                               $continue = false;
+                               
+                               break;
+                       }
+               }
+       }
+       
+       // We can read the file(s)
+       if($continue) {
+               // We get the file MIME type
+               $mime = strtolower(preg_replace('/(^)(.+)(\.)(.+)($)/i', '$4', $file));
+               
+               // We set up a known MIME type (and some other headers)
+               if(($type == 'css') || ($type == 'js')) {
+                       // DEFLATE header
+                       if($deflate_support)
+                               header('Content-Encoding: deflate');
+                       
+                       // MIME header
+                       if($type == 'css')
+                               header('Content-Type: text/css; charset=utf-8');
+                       else if($type == 'js')
+                               header('Content-Type: application/javascript; charset=utf-8');
+               }
+               
+               else if($mime == 'png')
+                       header('Content-Type: image/png');
+               else if($mime == 'gif')
+                       header('Content-Type: image/gif');
+               else if(($mime == 'jpg') || ($mime == 'jpeg'))
+                       header('Content-Type: image/jpeg');
+               else if($mime == 'bmp')
+                       header('Content-Type: image/bmp');
+               else if(($mime == 'oga') || ($mime == 'ogg'))
+                       header('Content-Type: audio/ogg');
+               
+               // Catch the file MIME type
+               else
+                       header('Content-Type: '.getFileMIME($path));
+               
+               // Read the text file(s) (CSS & JS)
+               if(($type == 'css') || ($type == 'js')) {
+                       // If there's a cache file, read it
+                       if(hasCache($cache_lang) && !$is_developer) {
+                               $cache_read = readCache($cache_lang);
+                               
+                               if($deflate_support || !$has_compression)
+                                       echo $cache_read;
+                               else
+                                       echo gzinflate($cache_read);
+                       }
+                       
+                       // Else, we generate the cache
+                       else {
+                               // First try to read the cache reference
+                               if(hasCache($cache_hash) && !$is_developer) {
+                                       // Read the reference
+                                       $cache_reference = readCache($cache_hash);
+                                       
+                                       // Filter the cache reference
+                                       if($has_compression)
+                                               $output = gzinflate($cache_reference);
+                                       else
+                                               $output = $cache_reference;
+                               }
+                               
+                               // No cache reference, we should generate it
+                               else {
+                                       // Initialize the loop
+                                       $looped = '';
+                                       
+                                       // Add the content of the current file
+                                       foreach($array as $current)
+                                               $looped .= rmBOM(file_get_contents($dir.$current))."\n";
+                                       
+                                       // Filter the CSS
+                                       if($type == 'css') {
+                                               // Apply the CSS logos
+                                               $looped = setLogos($looped, $array);
+                                               
+                                               // Apply the CSS background
+                                               $looped = setBackground($looped);
+                                               
+                                               // Set the Get API paths
+                                               $looped = setPath($looped, $hash, HOST_STATIC, $type, '');
+                                       }
+                                       
+                                       // Optimize the code rendering
+                                       if($type == 'css') {
+                                               // Can minify the CSS
+                                               if($has_compression && !$is_developer)
+                                                       $output = compressCSS($looped);
+                                               else
+                                                       $output = $looped;
+                                       }
+                                       
+                                       else {
+                                               // Can minify the JS (sloooooow!)
+                                               if($has_compression && !$is_developer) {
+                                                       require_once('./jsmin.php');
+                                                       $output = JSMin::minify($looped);
+                                               }
+                                               
+                                               else
+                                                       $output = $looped;
+                                       }
+                                       
+                                       // Generate the reference cache
+                                       if($has_compression)
+                                               $final = gzdeflate($output, 9);
+                                       else
+                                               $final = $output;
+                                       
+                                       // Write it!
+                                       genCache($final, $is_developer, $cache_hash);
+                               }
+                               
+                               // Filter the JS
+                               if($type == 'js') {
+                                       // Set the JS locales
+                                       $output = setLocales($output, $locale);
+                                       
+                                       // Set the JS configuration
+                                       $output = setConfiguration($output, $locale, $version, uploadMaxSize());
+                                       
+                                       // Set the Get API paths
+                                       $output = setPath($output, $hash, HOST_STATIC, $type, $locale);
+                                       
+                                       // Translate the JS script
+                                       require_once('./gettext.php');
+                                       includeTranslation($locale, 'main');
+                                       $output = setTranslation($output);
+                                       
+                                       // Generate the cache
+                                       if($has_compression)
+                                               $final = gzdeflate($output, 9);
+                                       else
+                                               $final = $output;
+                                       
+                                       // Write it!
+                                       genCache($final, $is_developer, $cache_lang);
+                               }
+                               
+                               // Output a well-encoded string
+                               if($deflate_support || !$has_compression)
+                                       echo $final;
+                               else
+                                       echo gzinflate($final);
+                       }
+               }
+               
+               // Read the binary file (PNG, OGA and others)
+               else
+                       readfile($path);
+               
+               exit;
+       }
+       
+       // The file was not found
+       header('Status: 404 Not Found', true, 404);
+       exit('HTTP/1.1 404 Not Found');
+}
+
+// The request is not correct
+header('Status: 400 Bad Request', true, 400);
+exit('HTTP/1.1 400 Bad Request');
+
+?>
diff --git a/jappixmini/jappix/php/gettext.php b/jappixmini/jappix/php/gettext.php
new file mode 100644 (file)
index 0000000..f04b77d
--- /dev/null
@@ -0,0 +1,949 @@
+<?php
+
+/*
+   Copyright (c) 2003, 2005, 2006, 2009 Danilo Segan <danilo@kvota.net>.
+
+   This file is part of PHP-gettext.
+
+   PHP-gettext is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   PHP-gettext is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with PHP-gettext; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+ * MODIFIED FOR THE JAPPIX PROJECT
+ * Last revision: 10/11/10
+ */
+
+  // Simple class to wrap file streams, string streams, etc.
+  // seek is essential, and it should be byte stream
+class StreamReader {
+  // should return a string [FIXME: perhaps return array of bytes?]
+  function read($bytes) {
+    return false;
+  }
+
+  // should return new position
+  function seekto($position) {
+    return false;
+  }
+
+  // returns current position
+  function currentpos() {
+    return false;
+  }
+
+  // returns length of entire stream (limit for seekto()s)
+  function length() {
+    return false;
+  }
+};
+
+class StringReader {
+  var $_pos;
+  var $_str;
+
+  function StringReader($str='') {
+    $this->_str = $str;
+    $this->_pos = 0;
+  }
+
+  function read($bytes) {
+    $data = substr($this->_str, $this->_pos, $bytes);
+    $this->_pos += $bytes;
+    if (strlen($this->_str)<$this->_pos)
+      $this->_pos = strlen($this->_str);
+
+    return $data;
+  }
+
+  function seekto($pos) {
+    $this->_pos = $pos;
+    if (strlen($this->_str)<$this->_pos)
+      $this->_pos = strlen($this->_str);
+    return $this->_pos;
+  }
+
+  function currentpos() {
+    return $this->_pos;
+  }
+
+  function length() {
+    return strlen($this->_str);
+  }
+
+};
+
+
+class FileReader {
+  var $_pos;
+  var $_fd;
+  var $_length;
+
+  function FileReader($filename) {
+    if (file_exists($filename)) {
+
+      $this->_length=filesize($filename);
+      $this->_pos = 0;
+      $this->_fd = fopen($filename,'rb');
+      if (!$this->_fd) {
+        $this->error = 3; // Cannot read file, probably permissions
+        return false;
+      }
+    } else {
+      $this->error = 2; // File doesn't exist
+      return false;
+    }
+  }
+
+  function read($bytes) {
+    if ($bytes) {
+      fseek($this->_fd, $this->_pos);
+
+      // PHP 5.1.1 does not read more than 8192 bytes in one fread()
+      // the discussions at PHP Bugs suggest it's the intended behaviour
+      $data = '';
+      while ($bytes > 0) {
+        $chunk  = fread($this->_fd, $bytes);
+        $data  .= $chunk;
+        $bytes -= strlen($chunk);
+      }
+      $this->_pos = ftell($this->_fd);
+
+      return $data;
+    } else return '';
+  }
+
+  function seekto($pos) {
+    fseek($this->_fd, $pos);
+    $this->_pos = ftell($this->_fd);
+    return $this->_pos;
+  }
+
+  function currentpos() {
+    return $this->_pos;
+  }
+
+  function length() {
+    return $this->_length;
+  }
+
+  function close() {
+    fclose($this->_fd);
+  }
+
+};
+
+// Preloads entire file in memory first, then creates a StringReader
+// over it (it assumes knowledge of StringReader internals)
+class CachedFileReader extends StringReader {
+  function CachedFileReader($filename) {
+    if (file_exists($filename)) {
+
+      $length=filesize($filename);
+      $fd = fopen($filename,'rb');
+
+      if (!$fd) {
+        $this->error = 3; // Cannot read file, probably permissions
+        return false;
+      }
+      $this->_str = fread($fd, $length);
+      fclose($fd);
+
+    } else {
+      $this->error = 2; // File doesn't exist
+      return false;
+    }
+  }
+};
+
+/*
+   Copyright (c) 2003, 2009 Danilo Segan <danilo@kvota.net>.
+   Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
+
+   This file is part of PHP-gettext.
+
+   PHP-gettext is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   PHP-gettext is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with PHP-gettext; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/**
+ * Provides a simple gettext replacement that works independently from
+ * the system's gettext abilities.
+ * It can read MO files and use them for translating strings.
+ * The files are passed to gettext_reader as a Stream (see streams.php)
+ *
+ * This version has the ability to cache all strings and translations to
+ * speed up the string lookup.
+ * While the cache is enabled by default, it can be switched off with the
+ * second parameter in the constructor (e.g. whenusing very large MO files
+ * that you don't want to keep in memory)
+ */
+class gettext_reader {
+  //public:
+   var $error = 0; // public variable that holds error code (0 if no error)
+
+   //private:
+  var $BYTEORDER = 0;        // 0: low endian, 1: big endian
+  var $STREAM = NULL;
+  var $short_circuit = false;
+  var $enable_cache = false;
+  var $originals = NULL;      // offset of original table
+  var $translations = NULL;    // offset of translation table
+  var $pluralheader = NULL;    // cache header field for plural forms
+  var $total = 0;          // total string count
+  var $table_originals = NULL;  // table for original strings (offsets)
+  var $table_translations = NULL;  // table for translated strings (offsets)
+  var $cache_translations = NULL;  // original -> translation mapping
+
+
+  /* Methods */
+
+
+  /**
+   * Reads a 32bit Integer from the Stream
+   *
+   * @access private
+   * @return Integer from the Stream
+   */
+  function readint() {
+      if ($this->BYTEORDER == 0) {
+        // low endian
+        $input=unpack('V', $this->STREAM->read(4));
+        return array_shift($input);
+      } else {
+        // big endian
+        $input=unpack('N', $this->STREAM->read(4));
+        return array_shift($input);
+      }
+    }
+
+  function read($bytes) {
+    return $this->STREAM->read($bytes);
+  }
+
+  /**
+   * Reads an array of Integers from the Stream
+   *
+   * @param int count How many elements should be read
+   * @return Array of Integers
+   */
+  function readintarray($count) {
+    if ($this->BYTEORDER == 0) {
+        // low endian
+        return unpack('V'.$count, $this->STREAM->read(4 * $count));
+      } else {
+        // big endian
+        return unpack('N'.$count, $this->STREAM->read(4 * $count));
+      }
+  }
+
+  /**
+   * Constructor
+   *
+   * @param object Reader the StreamReader object
+   * @param boolean enable_cache Enable or disable caching of strings (default on)
+   */
+  function gettext_reader($Reader, $enable_cache = true) {
+    // If there isn't a StreamReader, turn on short circuit mode.
+    if (! $Reader || isset($Reader->error) ) {
+      $this->short_circuit = true;
+      return;
+    }
+
+    // Caching can be turned off
+    $this->enable_cache = $enable_cache;
+
+    $MAGIC1 = "\x95\x04\x12\xde";
+    $MAGIC2 = "\xde\x12\x04\x95";
+
+    $this->STREAM = $Reader;
+    $magic = $this->read(4);
+    if ($magic == $MAGIC1) {
+      $this->BYTEORDER = 1;
+    } elseif ($magic == $MAGIC2) {
+      $this->BYTEORDER = 0;
+    } else {
+      $this->error = 1; // not MO file
+      return false;
+    }
+
+    // FIXME: Do we care about revision? We should.
+    $revision = $this->readint();
+
+    $this->total = $this->readint();
+    $this->originals = $this->readint();
+    $this->translations = $this->readint();
+  }
+
+  /**
+   * Loads the translation tables from the MO file into the cache
+   * If caching is enabled, also loads all strings into a cache
+   * to speed up translation lookups
+   * 
+   * @access private
+   */
+  function load_tables() {
+    if (is_array($this->cache_translations) &&
+      is_array($this->table_originals) &&
+      is_array($this->table_translations))
+      return;
+
+    /* get original and translations tables */
+    $this->STREAM->seekto($this->originals);
+    $this->table_originals = $this->readintarray($this->total * 2);
+    $this->STREAM->seekto($this->translations);
+    $this->table_translations = $this->readintarray($this->total * 2);
+
+    if ($this->enable_cache) {
+      $this->cache_translations = array ();
+      /* read all strings in the cache */
+      for ($i = 0; $i < $this->total; $i++) {
+        $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
+        $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
+        $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
+        $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
+        $this->cache_translations[$original] = $translation;
+      }
+    }
+  }
+
+  /**
+   * Returns a string from the "originals" table
+   *
+   * @access private
+   * @param int num Offset number of original string
+   * @return string Requested string if found, otherwise ''
+   */
+  function get_original_string($num) {
+    $length = $this->table_originals[$num * 2 + 1];
+    $offset = $this->table_originals[$num * 2 + 2];
+    if (! $length)
+      return '';
+    $this->STREAM->seekto($offset);
+    $data = $this->STREAM->read($length);
+    return (string)$data;
+  }
+
+  /**
+   * Returns a string from the "translations" table
+   *
+   * @access private
+   * @param int num Offset number of original string
+   * @return string Requested string if found, otherwise ''
+   */
+  function get_translation_string($num) {
+    $length = $this->table_translations[$num * 2 + 1];
+    $offset = $this->table_translations[$num * 2 + 2];
+    if (! $length)
+      return '';
+    $this->STREAM->seekto($offset);
+    $data = $this->STREAM->read($length);
+    return (string)$data;
+  }
+
+  /**
+   * Binary search for string
+   *
+   * @access private
+   * @param string string
+   * @param int start (internally used in recursive function)
+   * @param int end (internally used in recursive function)
+   * @return int string number (offset in originals table)
+   */
+  function find_string($string, $start = -1, $end = -1) {
+    if (($start == -1) or ($end == -1)) {
+      // find_string is called with only one parameter, set start end end
+      $start = 0;
+      $end = $this->total;
+    }
+    if (abs($start - $end) <= 1) {
+      // We're done, now we either found the string, or it doesn't exist
+      $txt = $this->get_original_string($start);
+      if ($string == $txt)
+        return $start;
+      else
+        return -1;
+    } else if ($start > $end) {
+      // start > end -> turn around and start over
+      return $this->find_string($string, $end, $start);
+    } else {
+      // Divide table in two parts
+      $half = (int)(($start + $end) / 2);
+      $cmp = strcmp($string, $this->get_original_string($half));
+      if ($cmp == 0)
+        // string is exactly in the middle => return it
+        return $half;
+      else if ($cmp < 0)
+        // The string is in the upper half
+        return $this->find_string($string, $start, $half);
+      else
+        // The string is in the lower half
+        return $this->find_string($string, $half, $end);
+    }
+  }
+
+  /**
+   * Translates a string
+   *
+   * @access public
+   * @param string string to be translated
+   * @return string translated string (or original, if not found)
+   */
+  function translate($string) {
+    if ($this->short_circuit)
+      return $string;
+    $this->load_tables();
+
+    if ($this->enable_cache) {
+      // Caching enabled, get translated string from cache
+      if (array_key_exists($string, $this->cache_translations))
+        return $this->cache_translations[$string];
+      else
+        return $string;
+    } else {
+      // Caching not enabled, try to find string
+      $num = $this->find_string($string);
+      if ($num == -1)
+        return $string;
+      else
+        return $this->get_translation_string($num);
+    }
+  }
+
+  /**
+   * Sanitize plural form expression for use in PHP eval call.
+   *
+   * @access private
+   * @return string sanitized plural form expression
+   */
+  function sanitize_plural_expression($expr) {
+    // Get rid of disallowed characters.
+    $expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);
+
+    // Add parenthesis for tertiary '?' operator.
+    $expr .= ';';
+    $res = '';
+    $p = 0;
+    for ($i = 0; $i < strlen($expr); $i++) {
+      $ch = $expr[$i];
+      switch ($ch) {
+      case '?':
+        $res .= ' ? (';
+        $p++;
+        break;
+      case ':':
+        $res .= ') : (';
+        break;
+      case ';':
+        $res .= str_repeat( ')', $p) . ';';
+        $p = 0;
+        break;
+      default:
+        $res .= $ch;
+      }
+    }
+    return $res;
+  }
+
+  /**
+   * Get possible plural forms from MO header
+   *
+   * @access private
+   * @return string plural form header
+   */
+  function get_plural_forms() {
+    // lets assume message number 0 is header
+    // this is true, right?
+    $this->load_tables();
+
+    // cache header field for plural forms
+    if (! is_string($this->pluralheader)) {
+      if ($this->enable_cache) {
+        $header = $this->cache_translations[""];
+      } else {
+        $header = $this->get_translation_string(0);
+      }
+      if (eregi("plural-forms: ([^\n]*)\n", $header, $regs))
+        $expr = $regs[1];
+      else
+        $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
+
+      $this->pluralheader = $this->sanitize_plural_expression($expr);
+    }
+    return $this->pluralheader;
+  }
+
+  /**
+   * Detects which plural form to take
+   *
+   * @access private
+   * @param n count
+   * @return int array index of the right plural form
+   */
+  function select_string($n) {
+    $string = $this->get_plural_forms();
+    $string = str_replace('nplurals',"\$total",$string);
+    $string = str_replace("n",$n,$string);
+    $string = str_replace('plural',"\$plural",$string);
+
+    $total = 0;
+    $plural = 0;
+
+    eval("$string");
+    if ($plural >= $total) $plural = $total - 1;
+    return $plural;
+  }
+
+  /**
+   * Plural version of gettext
+   *
+   * @access public
+   * @param string single
+   * @param string plural
+   * @param string number
+   * @return translated plural form
+   */
+  function ngettext($single, $plural, $number) {
+    if ($this->short_circuit) {
+      if ($number != 1)
+        return $plural;
+      else
+        return $single;
+    }
+
+    // find out the appropriate form
+    $select = $this->select_string($number);
+
+    // this should contains all strings separated by NULLs
+    $key = $single.chr(0).$plural;
+
+
+    if ($this->enable_cache) {
+      if (! array_key_exists($key, $this->cache_translations)) {
+        return ($number != 1) ? $plural : $single;
+      } else {
+        $result = $this->cache_translations[$key];
+        $list = explode(chr(0), $result);
+        return $list[$select];
+      }
+    } else {
+      $num = $this->find_string($key);
+      if ($num == -1) {
+        return ($number != 1) ? $plural : $single;
+      } else {
+        $result = $this->get_translation_string($num);
+        $list = explode(chr(0), $result);
+        return $list[$select];
+      }
+    }
+  }
+
+}
+
+/*
+   Copyright (c) 2005 Steven Armstrong <sa at c-area dot ch>
+   Copyright (c) 2009 Danilo Segan <danilo@kvota.net>
+
+   Drop in replacement for native gettext.
+
+   This file is part of PHP-gettext.
+
+   PHP-gettext is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   PHP-gettext is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with PHP-gettext; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+/*
+LC_CTYPE        0
+LC_NUMERIC      1
+LC_TIME         2
+LC_COLLATE      3
+LC_MONETARY     4
+LC_MESSAGES     5
+LC_ALL          6
+*/
+
+
+// LC_MESSAGES is not available if php-gettext is not loaded
+// while the other constants are already available from session extension.
+if (!defined('LC_MESSAGES')) {
+  define('LC_MESSAGES',        5);
+}
+
+// Variables
+
+global $text_domains, $default_domain, $LC_CATEGORIES, $EMULATEGETTEXT, $CURRENTLOCALE;
+$text_domains = array();
+$default_domain = 'messages';
+$LC_CATEGORIES = array('LC_CTYPE', 'LC_NUMERIC', 'LC_TIME', 'LC_COLLATE', 'LC_MONETARY', 'LC_MESSAGES', 'LC_ALL');
+$EMULATEGETTEXT = 0;
+$CURRENTLOCALE = '';
+
+/* Class to hold a single domain included in $text_domains. */
+class domain {
+  var $l10n;
+  var $path;
+  var $codeset;
+}
+
+// Utility functions
+
+/**
+ * Utility function to get a StreamReader for the given text domain.
+ */
+function _get_reader($domain=null, $category=5, $enable_cache=true) {
+    global $text_domains, $default_domain, $LC_CATEGORIES;
+    if (!isset($domain)) $domain = $default_domain;
+    if (!isset($text_domains[$domain]->l10n)) {
+        // get the current locale
+        $locale = _setlocale(LC_MESSAGES, 0);
+        $bound_path = isset($text_domains[$domain]->path) ?
+          $text_domains[$domain]->path : './';
+        $subpath = $LC_CATEGORIES[$category] ."/$domain.mo";
+        /* Figure out all possible locale names and start with the most
+           specific ones.  I.e. for sr_CS.UTF-8@latin, look through all of
+           sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr.
+        */
+        $locale_names = array();
+        if (preg_match("/([a-z]{2,3})"            // language code
+                       ."(_([A-Z]{2}))?"          // country code
+                       ."(\.([-A-Za-z0-9_]))?"    // charset
+                       ."(@([-A-Za-z0-9_]+))?/",  // @ modifier
+                       $locale, $matches)) {
+          
+          $lang = '';
+          $country = '';
+          $charset = '';
+          $modifier = '';
+          
+          if(isset($matches[1]))
+             $lang = $matches[1];
+          if(isset($matches[3]))
+             $country = $matches[3];
+          if(isset($matches[5]))
+             $charset = $matches[5];
+          if(isset($matches[7]))
+             $modifier = $matches[7];
+          
+          if ($modifier) {
+            $locale_names = array("${lang}_$country.$charset@$modifier",
+                                  "${lang}_$country@$modifier",
+                                  "$lang@$modifier");
+          }
+          array_push($locale_names,
+                     "${lang}_$country.$charset", "${lang}_$country", "$lang");
+        }
+        array_push($locale_names, $locale);
+
+        $input = null;
+        foreach ($locale_names as $locale) {
+          $full_path = $bound_path . $locale . "/" . $subpath;
+          if (file_exists($full_path)) {
+            $input = new FileReader($full_path);
+            break;
+          }
+        }
+
+        if (!array_key_exists($domain, $text_domains)) {
+          // Initialize an empty domain object.
+          $text_domains[$domain] = new domain();
+        }
+        $text_domains[$domain]->l10n = new gettext_reader($input,
+                                                          $enable_cache);
+    }
+    return $text_domains[$domain]->l10n;
+}
+
+/**
+ * Returns whether we are using our emulated gettext API or PHP built-in one.
+ */
+function locale_emulation() {
+    global $EMULATEGETTEXT;
+    return $EMULATEGETTEXT;
+}
+
+/**
+ * Checks if the current locale is supported on this system.
+ */
+function _check_locale() {
+    global $EMULATEGETTEXT;
+    return !$EMULATEGETTEXT;
+}
+
+/**
+ * Get the codeset for the given domain.
+ */
+function _get_codeset($domain=null) {
+    global $text_domains, $default_domain, $LC_CATEGORIES;
+    if (!isset($domain)) $domain = $default_domain;
+    return (isset($text_domains[$domain]->codeset))? $text_domains[$domain]->codeset : ini_get('mbstring.internal_encoding');
+}
+
+/**
+ * Convert the given string to the encoding set by bind_textdomain_codeset.
+ */
+function _encode($text) {
+    $source_encoding = mb_detect_encoding($text);
+    $target_encoding = _get_codeset();
+    if ($source_encoding != $target_encoding) {
+        return mb_convert_encoding($text, $target_encoding, $source_encoding);
+    }
+    else {
+        return $text;
+    }
+}
+
+
+
+
+// Custom implementation of the standard gettext related functions
+
+/**
+ * Sets a requested locale, if needed emulates it.
+ */
+function _setlocale($category, $locale) {
+    global $CURRENTLOCALE, $EMULATEGETTEXT;
+    if ($locale === 0) { // use === to differentiate between string "0"
+        if ($CURRENTLOCALE != '')
+            return $CURRENTLOCALE;
+        else
+            // obey LANG variable, maybe extend to support all of LC_* vars
+            // even if we tried to read locale without setting it first
+            return _setlocale($category, $CURRENTLOCALE);
+    } else {
+        $ret = 0;
+        if (function_exists('setlocale')) // I don't know if this ever happens ;)
+           $ret = setlocale($category, $locale);
+        if (($ret and $locale == '') or ($ret == $locale)) {
+            $EMULATEGETTEXT = 0;
+            $CURRENTLOCALE = $ret;
+        } else {
+          if ($locale == '') // emulate variable support
+             $CURRENTLOCALE = getenv('LANG');
+        else
+            $CURRENTLOCALE = $locale;
+            $EMULATEGETTEXT = 1;
+        }
+        // Allow locale to be changed on the go for one translation domain.
+        global $text_domains, $default_domain;
+        unset($text_domains[$default_domain]->l10n);
+        return $CURRENTLOCALE;
+    }
+}
+
+/**
+ * Sets the path for a domain.
+ */
+function _bindtextdomain($domain, $path) {
+    global $text_domains;
+    // ensure $path ends with a slash ('/' should work for both, but lets still play nice)
+    if (substr(php_uname(), 0, 7) == "Windows") {
+      if ($path[strlen($path)-1] != '\\' and $path[strlen($path)-1] != '/')
+        $path .= '\\';
+    } else {
+      if ($path[strlen($path)-1] != '/')
+        $path .= '/';
+    }
+    if (!array_key_exists($domain, $text_domains)) {
+      // Initialize an empty domain object.
+      $text_domains[$domain] = new domain();
+    }
+    $text_domains[$domain]->path = $path;
+}
+
+/**
+ * Specify the character encoding in which the messages from the DOMAIN message catalog will be returned.
+ */
+function _bind_textdomain_codeset($domain, $codeset) {
+    global $text_domains;
+    $text_domains[$domain]->codeset = $codeset;
+}
+
+/**
+ * Sets the default domain.
+ */
+function _textdomain($domain) {
+    global $default_domain;
+    $default_domain = $domain;
+}
+
+/**
+ * Lookup a message in the current domain.
+ */
+function _gettext($msgid) {
+    $l10n = _get_reader();
+    //return $l10n->translate($msgid);
+    return _encode($l10n->translate($msgid));
+}
+/**
+ * Alias for gettext.
+ */
+function __($msgid) {
+    return _gettext($msgid);
+}
+/**
+ * Plural version of gettext.
+ */
+function _ngettext($single, $plural, $number) {
+    $l10n = _get_reader();
+    //return $l10n->ngettext($single, $plural, $number);
+    return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+/**
+ * Override the current domain.
+ */
+function _dgettext($domain, $msgid) {
+    $l10n = _get_reader($domain);
+    //return $l10n->translate($msgid);
+    return _encode($l10n->translate($msgid));
+}
+/**
+ * Plural version of dgettext.
+ */
+function _dngettext($domain, $single, $plural, $number) {
+    $l10n = _get_reader($domain);
+    //return $l10n->ngettext($single, $plural, $number);
+    return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+/**
+ * Overrides the domain and category for a single lookup.
+ */
+function _dcgettext($domain, $msgid, $category) {
+    $l10n = _get_reader($domain, $category);
+    //return $l10n->translate($msgid);
+    return _encode($l10n->translate($msgid));
+}
+/**
+ * Plural version of dcgettext.
+ */
+function _dcngettext($domain, $single, $plural, $number, $category) {
+    $l10n = _get_reader($domain, $category);
+    //return $l10n->ngettext($single, $plural, $number);
+    return _encode($l10n->ngettext($single, $plural, $number));
+}
+
+
+
+// Wrappers to use if the standard gettext functions are available, but the current locale is not supported by the system.
+// Use the standard impl if the current locale is supported, use the custom impl otherwise.
+
+function T_setlocale($category, $locale) {
+    return _setlocale($category, $locale);
+}
+
+function T_bindtextdomain($domain, $path) {
+    if (_check_locale()) return bindtextdomain($domain, $path);
+    else return _bindtextdomain($domain, $path);
+}
+function T_bind_textdomain_codeset($domain, $codeset) {
+    // bind_textdomain_codeset is available only in PHP 4.2.0+
+    if (_check_locale() and function_exists('bind_textdomain_codeset')) return bind_textdomain_codeset($domain, $codeset);
+    else return _bind_textdomain_codeset($domain, $codeset);
+}
+function T_textdomain($domain) {
+    if (_check_locale()) return textdomain($domain);
+    else return _textdomain($domain);
+}
+function T_gettext($msgid) {
+    if (_check_locale()) return gettext($msgid);
+    else return _gettext($msgid);
+}
+function T_($msgid) {
+    if (_check_locale()) return _($msgid);
+    return __($msgid);
+}
+function T_ngettext($single, $plural, $number) {
+    if (_check_locale()) return ngettext($single, $plural, $number);
+    else return _ngettext($single, $plural, $number);
+}
+function T_dgettext($domain, $msgid) {
+    if (_check_locale()) return dgettext($domain, $msgid);
+    else return _dgettext($domain, $msgid);
+}
+function T_dngettext($domain, $single, $plural, $number) {
+    if (_check_locale()) return dngettext($domain, $single, $plural, $number);
+    else return _dngettext($domain, $single, $plural, $number);
+}
+function T_dcgettext($domain, $msgid, $category) {
+    if (_check_locale()) return dcgettext($domain, $msgid, $category);
+    else return _dcgettext($domain, $msgid, $category);
+}
+function T_dcngettext($domain, $single, $plural, $number, $category) {
+    if (_check_locale()) return dcngettext($domain, $single, $plural, $number, $category);
+    else return _dcngettext($domain, $single, $plural, $number, $category);
+}
+
+
+
+// Wrappers used as a drop in replacement for the standard gettext functions
+
+if (!function_exists('gettext')) {
+    function bindtextdomain($domain, $path) {
+        return _bindtextdomain($domain, $path);
+    }
+    function bind_textdomain_codeset($domain, $codeset) {
+        return _bind_textdomain_codeset($domain, $codeset);
+    }
+    function textdomain($domain) {
+        return _textdomain($domain);
+    }
+    function gettext($msgid) {
+        return _gettext($msgid);
+    }
+    function _($msgid) {
+        return __($msgid);
+    }
+    function ngettext($single, $plural, $number) {
+        return _ngettext($single, $plural, $number);
+    }
+    function dgettext($domain, $msgid) {
+        return _dgettext($domain, $msgid);
+    }
+    function dngettext($domain, $single, $plural, $number) {
+        return _dngettext($domain, $single, $plural, $number);
+    }
+    function dcgettext($domain, $msgid, $category) {
+        return _dcgettext($domain, $msgid, $category);
+    }
+    function dcngettext($domain, $single, $plural, $number, $category) {
+        return _dcngettext($domain, $single, $plural, $number, $category);
+    }
+}
+
+?>
diff --git a/jappixmini/jappix/php/install.php b/jappixmini/jappix/php/install.php
new file mode 100644 (file)
index 0000000..ae0ff70
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Install PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 25/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define the configuration folder
+$conf_folder = JAPPIX_BASE.'/store/conf';
+
+// Initialize the step
+$step = 1;
+
+// Initialize some vars
+$form_parent = 'install';
+$user_name = '';
+$user_password = '';
+$valid_user = true;
+
+if(isset($_POST['step']) && !empty($_POST['step'])) {
+       $step = intval($_POST['step']);
+       
+       switch($step) {
+               // Administrator account configuration submitted
+               case 3:
+                       include(JAPPIX_BASE.'/php/post-users.php');
+                       break;
+               
+               // Main configuration submitted
+               case 4:
+                       include(JAPPIX_BASE.'/php/post-main.php');
+                       break;
+               
+               // Hosts configuration submitted
+               case 5:
+                       include(JAPPIX_BASE.'/php/post-hosts.php');
+                       break;
+       }
+}
+
+// Not frozen on the previous step?
+if(!isset($_POST['check']) && (isset($_POST['submit']) || isset($_POST['finish']))) {
+       // Checks the current step is valid
+       if(($step >= 2) && !is_dir($conf_folder))
+               $step = 2;
+       else if(($step >= 3) && !usersConfName())
+               $step = 3;
+       else if(($step >= 4) && !file_exists($conf_folder.'/main.xml'))
+               $step = 4;
+       else if(($step >= 5) && !file_exists($conf_folder.'/hosts.xml'))
+               $step = 5;
+       else
+               $step++;
+}
+
+// These steps are not available
+if(($step > 6) || !is_int($step))
+       $step = 6;
+
+// Get the current step title
+$names = array(
+       T_("Welcome"),
+       T_("Storage configuration"),
+       T_("Administrator account"),
+       T_("Main configuration"),
+       T_("Hosts configuration"),
+       T_("Services installation")
+);
+
+// Continue marker
+$continue = true;
+
+// Form action
+if($step < 6)
+       $form_action = './?m=install'.keepGet('m', false);
+else
+       $form_action = './'.keepGet('m', true);
+
+?>
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <meta name="robots" content="none" />
+       <title><?php _e("Jappix installation"); ?> &bull; <?php echo($names[$step - 1]); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+       <?php echoGetFiles($hash, '', 'css', 'install.xml', ''); echo "\n"; ?>
+       <!--[if lt IE 9]><?php echoGetFiles($hash, '', 'css', '', 'ie.css'); ?><![endif]-->
+</head>
+
+<body class="body-images">
+       <form id="install" method="post" action="<?php echo $form_action; ?>">
+               <div id="install-top">
+                       <div class="logo install-images"><?php _e("Installation"); ?></div>
+                       <div class="step"><?php echo $step; ?> <span>/ 6</span></div>
+                       <div class="clear"></div>
+                       
+                       <input type="hidden" name="step" value="<?php echo($step); ?>" />
+               </div>
+               
+               <div id="install-content">
+                       <?php
+                       
+                       // First step: welcome
+                       if($step == 1) { ?>
+                               <h3 class="start install-images"><?php _e("Welcome to the Jappix installation!"); ?></h3>
+                               
+                               <p><?php _e("This tool will help you fastly install Jappix, the first full-featured XMPP-based social platform, on your server. You don't even need any technical knowledge."); ?></p>
+                               <p><?php _e("Let's have a look at the installation steps:"); ?></p>
+                               
+                               <ol>
+                                       <li><?php _e("Welcome"); ?></li>
+                                       <li><?php _e("Storage configuration"); ?></li>
+                                       <li><?php _e("Administrator account"); ?></li>
+                                       <li><?php _e("Main configuration"); ?></li>
+                                       <li><?php _e("Hosts configuration"); ?></li>
+                                       <li><?php _e("Services installation"); ?></li>
+                               </ol>
+                               
+                               <p><?php printf(T_("If the current language does not match yours (%1s), you can make Jappix speak %2s it will be saved."), getLanguageName($locale), languageSwitcher($locale)); ?></p>
+                               
+                               <p><?php _e("If you want to get some help about the Jappix installation and configuration, you can use our whole documentation, available at:"); ?> <a href="http://codingteam.net/project/jappix/doc" target="_blank">http://codingteam.net/project/jappix/doc</a></p>
+                               
+                               <p><?php _e("It's time to build your own social cloud: just go to the next step!"); ?></p>
+                       <?php }
+                       
+                       // Second step: storage configuration
+                       else if($step == 2) { ?>
+                               <h3 class="storage install-images"><?php _e("Storage configuration"); ?></h3>
+                               
+                               <p><?php _e("Jappix stores persistent data (such as shared files, chat logs, your own music and its configuration) into a single secured storage folder."); ?></p>
+                               
+                               <p><?php printf(T_("Jappix must be able to write in this folder to create its sub-directories. If not, you must set the rights to %1s or change the folder owner to %2s (depending of your configuration)."), '<em>777</em>', '<em>www-data</em>'); ?></p>
+                               
+                               <?php if(is_writable(JAPPIX_BASE.'/store')) {
+                                       // Create the store tree
+                                       include(JAPPIX_BASE.'/php/store-tree.php');
+                               ?>
+                                       <p class="info bigspace success"><?php _e("The folder is writable, you can continue!"); ?></p>
+                               <?php }
+                               
+                               else {
+                                       $continue = false;
+                               ?>
+                                       <p class="info bigspace fail"><?php printf(T_("The folder is not writable, set the right permissions to the %s directory."), "<em>./store</em>"); ?></p>
+                               <?php } ?>
+                       <?php }
+                       
+                       // Third step: administrator account
+                       else if($step == 3) { ?>
+                               <h3 class="account  install-images"><?php _e("Administrator account"); ?></h3>
+                               
+                               <p><?php _e("Jappix offers you the possibility to manage your configuration, install new plugins or search for updates. That's why you must create an administrator account to access the manager."); ?></p>
+                               
+                               <p><?php _e("When Jappix will be installed, just click on the manager link on the home page to access it."); ?></p>
+                               
+                               <?php
+                               
+                               // Include the user add form
+                               include(JAPPIX_BASE.'/php/form-users.php');
+                               
+                               if(!$valid_user) { ?>
+                                       <p class="info bigspace fail"><?php _e("Oops, you missed something or the two passwords do not match!"); ?></p>
+                               <?php }
+                       }
+                       
+                       // Fourth step: main configuration
+                       else if($step == 4) { ?>
+                               <h3 class="main install-images"><?php _e("Main configuration"); ?></h3>
+                               
+                               <p><?php _e("Jappix needs that you specify some values to work. Please correct the following inputs (or keep the default values, which are sufficient for most people)."); ?></p>
+                               
+                               <p><?php _e("Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."); ?></p>
+                               
+                               <?php
+                               
+                               // Define the main configuration variables
+                               include(JAPPIX_BASE.'/php/vars-main.php');
+                               
+                               // Are we using developer mode?
+                               if(preg_match('/~dev/i', $version))
+                                       $developer = 'on';
+                               
+                               // Include the main configuration form
+                               include(JAPPIX_BASE.'/php/form-main.php');
+                       }
+                       
+                       // Fifth step: hosts configuration
+                       else if($step == 5) { ?>
+                               <h3 class="hosts install-images"><?php _e("Hosts configuration"); ?></h3>
+                               
+                               <p><?php _e("This page helps you specify the default hosts Jappix will connect to. You can leave it as it is and continue if you want to use the official service hosts."); ?></p>
+                               
+                               <p><?php _e("Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."); ?></p>
+                               
+                               <p><?php _e("Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."); ?></p>
+                               
+                               <?php
+                               
+                               // Define the hosts configuration variables
+                               include(JAPPIX_BASE.'/php/vars-hosts.php');
+                               
+                               // Include the hosts configuration form
+                               include(JAPPIX_BASE.'/php/form-hosts.php');
+                       }
+                       
+                       // Last step: services installation
+                       else if($step == 6) { ?>
+                               <h3 class="services install-images"><?php _e("Services installation"); ?></h3>
+                               
+                               <p><?php _e("You can install some extra softwares on your server, to extend your Jappix features. Some others might be modified, because of security restrictions which are set by default."); ?></p>
+                               <p><?php _e("To perform this, you must be able to access your server's shell and be logged in as root. Remember this is facultative, Jappix will work without these modules, but some of its features will be unavailable."); ?></p>
+                               
+                               <?php
+                               
+                               // Write the installed marker
+                               writeXML('conf', 'installed', '<installed>true</installed>');
+                               
+                               // Checks some services are installed
+                               $services_functions = array('gd_info', 'curl_init');
+                               $services_names = array('GD', 'cURL');
+                               $services_packages = array('php5-gd', 'php5-curl');
+                               
+                               for($i = 0; $i < count($services_names); $i++) {
+                                       $service_class = 'info smallspace';
+                                       
+                                       // First info?
+                                       if($i == 0)
+                                               $service_class .= ' first';
+                                       
+                                       // Service installed?
+                                       if(function_exists($services_functions[$i])) { ?>
+                                               <p class="<?php echo($service_class) ?> success"><?php printf(T_("%s is installed on your system."), $services_names[$i]); ?></p>
+                                       <?php }
+                                       
+                                       // Missing service!
+                                       else { ?>
+                                               <p class="<?php echo($service_class) ?> fail"><?php printf(T_("%1s is not installed on your system, you should install %2s."), $services_names[$i], '<em>'.$services_packages[$i].'</em>'); ?></p>
+                                       <?php }
+                               }
+                               
+                               // Checks the upload size limit
+                               $upload_max = uploadMaxSize();
+                               $upload_human = formatBytes($upload_max);
+                               
+                               if($upload_max >= 7000000) { ?>
+                                       <p class="info smallspace last success"><?php printf(T_("PHP maximum upload size is sufficient (%s)."), $upload_human); ?></p>
+                               <?php }
+                               
+                               else { ?>
+                                       <p class="info smallspace last fail"><?php printf(T_("PHP maximum upload size is not sufficient (%1s), you should define it to %2s in %3s."), $upload_human, '8M', '<em>php.ini</em>'); ?></p>
+                               <?php } ?>
+                               
+                               <p><?php _e("After you finished the setup, Jappix will generate the cache files. It might be slow, just wait until the application is displayed and do not press any button."); ?></p>
+                               
+                               <p><?php _e("Thanks for using Jappix!"); ?></p>
+                       <?php } ?>
+               </div>
+               
+               <div id="install-buttons">
+                       <?php if($continue && ($step < 6)) { ?>
+                               <input type="submit" name="submit" value="<?php _e("Next"); ?> »" />
+                       <?php } if($step == 6) { ?>
+                               <input type="submit" name="finish" value="<?php _e("Finish"); ?> »" />
+                       <?php } if(!$continue) { ?>
+                               <input type="submit" name="check" value="<?php _e("Check again"); ?>" />
+                       <?php } ?>
+                       
+                       <div class="clear"></div>
+               </div>
+       </form>
+</body>
+
+</html>
+
+<!-- Jappix Install <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/jsmin.php b/jappixmini/jappix/php/jsmin.php
new file mode 100644 (file)
index 0000000..5c3f881
--- /dev/null
@@ -0,0 +1,375 @@
+<?php
+/**
+ * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
+ *
+ * This is pretty much a direct port of jsmin.c to PHP with just a few
+ * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
+ * outputs to stdout, this library accepts a string as input and returns another
+ * string as output.
+ *
+ * PHP 5 or higher is required.
+ *
+ * Permission is hereby granted to use this version of the library under the
+ * same terms as jsmin.c, which has the following license:
+ *
+ * --
+ * Copyright (c) 2002 Douglas Crockford  (www.crockford.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * The Software shall be used for Good, not Evil.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * --
+ *
+ * @package JSMin
+ * @author Ryan Grove <ryan@wonko.com>
+ * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
+ * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
+ * @license http://opensource.org/licenses/mit-license.php MIT License
+ * @version 1.1.1 (2008-03-02)
+ * @link https://github.com/rgrove/jsmin-php/
+ */
+
+class JSMin {
+  const ORD_LF            = 10;
+  const ORD_SPACE         = 32;
+  const ACTION_KEEP_A     = 1;
+  const ACTION_DELETE_A   = 2;
+  const ACTION_DELETE_A_B = 3;
+
+  protected $a           = '';
+  protected $b           = '';
+  protected $input       = '';
+  protected $inputIndex  = 0;
+  protected $inputLength = 0;
+  protected $lookAhead   = null;
+  protected $output      = '';
+
+  // -- Public Static Methods --------------------------------------------------
+
+  /**
+   * Minify Javascript
+   *
+   * @uses __construct()
+   * @uses min()
+   * @param string $js Javascript to be minified
+   * @return string
+   */
+  public static function minify($js) {
+    $jsmin = new JSMin($js);
+    return $jsmin->min();
+  }
+
+  // -- Public Instance Methods ------------------------------------------------
+
+  /**
+   * Constructor
+   *
+   * @param string $input Javascript to be minified
+   */
+  public function __construct($input) {
+    $this->input       = str_replace("\r\n", "\n", $input);
+    $this->inputLength = strlen($this->input);
+  }
+
+  // -- Protected Instance Methods ---------------------------------------------
+
+  /**
+   * Action -- do something! What to do is determined by the $command argument.
+   *
+   * action treats a string as a single character. Wow!
+   * action recognizes a regular expression if it is preceded by ( or , or =.
+   *
+   * @uses next()
+   * @uses get()
+   * @throws JSMinException If parser errors are found:
+   *         - Unterminated string literal
+   *         - Unterminated regular expression set in regex literal
+   *         - Unterminated regular expression literal
+   * @param int $command One of class constants:
+   *      ACTION_KEEP_A      Output A. Copy B to A. Get the next B.
+   *      ACTION_DELETE_A    Copy B to A. Get the next B. (Delete A).
+   *      ACTION_DELETE_A_B  Get the next B. (Delete B).
+  */
+  protected function action($command) {
+    switch($command) {
+      case self::ACTION_KEEP_A:
+        $this->output .= $this->a;
+
+      case self::ACTION_DELETE_A:
+        $this->a = $this->b;
+
+        if ($this->a === "'" || $this->a === '"') {
+          for (;;) {
+            $this->output .= $this->a;
+            $this->a       = $this->get();
+
+            if ($this->a === $this->b) {
+              break;
+            }
+
+            if (ord($this->a) <= self::ORD_LF) {
+              throw new JSMinException('Unterminated string literal.');
+            }
+
+            if ($this->a === '\\') {
+              $this->output .= $this->a;
+              $this->a       = $this->get();
+            }
+          }
+        }
+
+      case self::ACTION_DELETE_A_B:
+        $this->b = $this->next();
+
+        if ($this->b === '/' && (
+            $this->a === '(' || $this->a === ',' || $this->a === '=' ||
+            $this->a === ':' || $this->a === '[' || $this->a === '!' ||
+            $this->a === '&' || $this->a === '|' || $this->a === '?' ||
+            $this->a === '{' || $this->a === '}' || $this->a === ';' ||
+            $this->a === "\n" )) {
+
+          $this->output .= $this->a . $this->b;
+
+          for (;;) {
+            $this->a = $this->get();
+
+            if ($this->a === '[') {
+              /*
+                inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460:
+                  return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value'));
+              */
+              for (;;) {
+                $this->output .= $this->a;
+                $this->a = $this->get();
+
+                if ($this->a === ']') {
+                    break;
+                } elseif ($this->a === '\\') {
+                  $this->output .= $this->a;
+                  $this->a       = $this->get();
+                } elseif (ord($this->a) <= self::ORD_LF) {
+                  throw new JSMinException('Unterminated regular expression set in regex literal.');
+                }
+              }
+            } elseif ($this->a === '/') {
+              break;
+            } elseif ($this->a === '\\') {
+              $this->output .= $this->a;
+              $this->a       = $this->get();
+            } elseif (ord($this->a) <= self::ORD_LF) {
+              throw new JSMinException('Unterminated regular expression literal.');
+            }
+
+            $this->output .= $this->a;
+          }
+
+          $this->b = $this->next();
+        }
+    }
+  }
+
+  /**
+   * Get next char. Convert ctrl char to space.
+   *
+   * @return string|null
+   */
+  protected function get() {
+    $c = $this->lookAhead;
+    $this->lookAhead = null;
+
+    if ($c === null) {
+      if ($this->inputIndex < $this->inputLength) {
+        $c = substr($this->input, $this->inputIndex, 1);
+        $this->inputIndex += 1;
+      } else {
+        $c = null;
+      }
+    }
+
+    if ($c === "\r") {
+      return "\n";
+    }
+
+    if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
+      return $c;
+    }
+
+    return ' ';
+  }
+
+  /**
+   * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character.
+   *
+   * @return bool
+   */
+  protected function isAlphaNum($c) {
+    return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
+  }
+
+  /**
+   * Perform minification, return result
+   *
+   * @uses action()
+   * @uses isAlphaNum()
+   * @return string
+   */
+  protected function min() {
+    $this->a = "\n";
+    $this->action(self::ACTION_DELETE_A_B);
+
+    while ($this->a !== null) {
+      switch ($this->a) {
+        case ' ':
+          if ($this->isAlphaNum($this->b)) {
+            $this->action(self::ACTION_KEEP_A);
+          } else {
+            $this->action(self::ACTION_DELETE_A);
+          }
+          break;
+
+        case "\n":
+          switch ($this->b) {
+            case '{':
+            case '[':
+            case '(':
+            case '+':
+            case '-':
+              $this->action(self::ACTION_KEEP_A);
+              break;
+
+            case ' ':
+              $this->action(self::ACTION_DELETE_A_B);
+              break;
+
+            default:
+              if ($this->isAlphaNum($this->b)) {
+                $this->action(self::ACTION_KEEP_A);
+              }
+              else {
+                $this->action(self::ACTION_DELETE_A);
+              }
+          }
+          break;
+
+        default:
+          switch ($this->b) {
+            case ' ':
+              if ($this->isAlphaNum($this->a)) {
+                $this->action(self::ACTION_KEEP_A);
+                break;
+              }
+
+              $this->action(self::ACTION_DELETE_A_B);
+              break;
+
+            case "\n":
+              switch ($this->a) {
+                case '}':
+                case ']':
+                case ')':
+                case '+':
+                case '-':
+                case '"':
+                case "'":
+                  $this->action(self::ACTION_KEEP_A);
+                  break;
+
+                default:
+                  if ($this->isAlphaNum($this->a)) {
+                    $this->action(self::ACTION_KEEP_A);
+                  }
+                  else {
+                    $this->action(self::ACTION_DELETE_A_B);
+                  }
+              }
+              break;
+
+            default:
+              $this->action(self::ACTION_KEEP_A);
+              break;
+          }
+      }
+    }
+
+    return $this->output;
+  }
+
+  /**
+   * Get the next character, skipping over comments. peek() is used to see
+   *  if a '/' is followed by a '/' or '*'.
+   *
+   * @uses get()
+   * @uses peek()
+   * @throws JSMinException On unterminated comment.
+   * @return string
+   */
+  protected function next() {
+    $c = $this->get();
+
+    if ($c === '/') {
+      switch($this->peek()) {
+        case '/':
+          for (;;) {
+            $c = $this->get();
+
+            if (ord($c) <= self::ORD_LF) {
+              return $c;
+            }
+          }
+
+        case '*':
+          $this->get();
+
+          for (;;) {
+            switch($this->get()) {
+              case '*':
+                if ($this->peek() === '/') {
+                  $this->get();
+                  return ' ';
+                }
+                break;
+
+              case null:
+                throw new JSMinException('Unterminated comment.');
+            }
+          }
+
+        default:
+          return $c;
+      }
+    }
+
+    return $c;
+  }
+
+  /**
+   * Get next char. If is ctrl character, translate to a space or newline.
+   *
+   * @uses get()
+   * @return string|null
+   */
+  protected function peek() {
+    $this->lookAhead = $this->get();
+    return $this->lookAhead;
+  }
+}
+
+// -- Exceptions ---------------------------------------------------------------
+class JSMinException extends Exception {}
+?>
\ No newline at end of file
diff --git a/jappixmini/jappix/php/manager.php b/jappixmini/jappix/php/manager.php
new file mode 100644 (file)
index 0000000..a1c683d
--- /dev/null
@@ -0,0 +1,839 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Manager PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Get the manager functions
+require_once(JAPPIX_BASE.'/php/functions-manager.php');
+
+// Session manager
+$id = 0;
+$login_fired = false;
+$logout_fired = false;
+$form_parent = 'manager';
+$user_password = '';
+$user_remember = '';
+$user = '';
+$password = '';
+$user_meta = T_("unknown");
+$user_name = '';
+$add_button = false;
+$remove_button = false;
+$save_button = false;
+$check_updates = false;
+
+// Start the session
+session_start();
+
+// Force the updates check?
+if(isset($_GET['p']) && ($_GET['p'] == 'check'))
+       $check_updates = true;
+
+// Login form is sent
+if(isset($_POST['login'])) {
+       // Form sent pointer
+       $login_fired = true;
+       
+       // Extract the user name
+       if(isset($_POST['admin_name']) && !empty($_POST['admin_name']))
+               $user = trim($_POST['admin_name']);
+       
+       if($user && (isset($_POST['admin_password']) && !empty($_POST['admin_password']))) {
+               // Get the password values
+               $password = genStrongHash(trim($_POST['admin_password']));
+               
+               // Write the session
+               $_SESSION['jappix_user'] = $user;
+               $_SESSION['jappix_password'] = $password;
+       }
+}
+
+// Session is set
+else if((isset($_SESSION['jappix_user']) && !empty($_SESSION['jappix_user'])) && (isset($_SESSION['jappix_password']) && !empty($_SESSION['jappix_password']))) {
+       // Form sent pointer
+       $login_fired = true;
+       
+       // Get the session values
+       $user = $_SESSION['jappix_user'];
+       $password = $_SESSION['jappix_password'];
+}
+
+// Validate the current session
+if($login_fired && isAdmin($user, $password))
+       $id = 1;
+
+// Any special page requested (and authorized)?
+if(($id != 0) && isset($_GET['a']) && !empty($_GET['a'])) {
+       // Extract the page name
+       $page_requested = $_GET['a'];
+       
+       switch($page_requested) {
+               // Logout request
+               case 'logout':
+                       // Remove the session
+                       unset($_SESSION['jappix_user']);
+                       unset($_SESSION['jappix_password']);
+                       
+                       // Set a logout marker
+                       $logout_fired = true;
+                       
+                       // Page ID
+                       $id = 0;
+                       
+                       break;
+               
+               // Configuration request
+               case 'configuration':
+                       // Allowed buttons
+                       $save_button = true;
+                       
+                       // Page ID
+                       $id = 2;
+                       
+                       break;
+               
+               // Hosts request
+               case 'hosts':
+                       // Allowed buttons
+                       $save_button = true;
+                       
+                       // Page ID
+                       $id = 3;
+                       
+                       break;
+               
+               // Storage request
+               case 'storage':
+                       // Allowed buttons
+                       $remove_button = true;
+                       
+                       // Page ID
+                       $id = 4;
+                       
+                       break;
+               
+               // Design request
+               case 'design':
+                       // Allowed buttons
+                       $save_button = true;
+                       $remove_button = true;
+                       
+                       // Page ID
+                       $id = 5;
+                       
+                       break;
+               
+               // Users request
+               case 'users':
+                       // Allowed buttons
+                       $add_button = true;
+                       $remove_button = true;
+                       
+                       // Page ID
+                       $id = 6;
+                       
+                       break;
+               
+               // Updates request
+               case 'updates':
+                       // Page ID
+                       $id = 7;
+                       
+                       break;
+               
+               // Default page when authorized (statistics)
+               default:
+                       // Page ID
+                       $id = 1;
+       }
+}
+
+// Page server-readable names
+$identifiers = array(
+       'login',
+       'statistics',
+       'configuration',
+       'hosts',
+       'storage',
+       'design',
+       'users',
+       'updates'
+);
+
+// Page human-readable names
+$names = array(
+       T_("Manager access"),
+       T_("Statistics"),
+       T_("Configuration"),
+       T_("Hosts"),
+       T_("Storage"),
+       T_("Design"),
+       T_("Users"),
+       T_("Updates")
+);
+
+// Any user for the meta?
+if($user && ($id != 0))
+       $user_meta = $user;
+
+// Define current page identifier & name
+$page_identifier = $identifiers[$id];
+$page_name = $names[$id];
+
+// Define the current page form action
+if($id == 0)
+       $form_action = keepGet('(m|a|p|k)', false);
+else
+       $form_action = keepGet('(m|p|k)', false);
+
+?>
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <meta name="robots" content="none" />
+       <title><?php _e("Jappix manager"); ?> &bull; <?php echo($page_name); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+       <?php echoGetFiles($hash, '', 'css', 'manager.xml', ''); echo "\n"; ?>
+       <!--[if lt IE 9]><?php echoGetFiles($hash, '', 'css', '', 'ie.css'); ?><![endif]-->
+</head>
+
+<body class="body-images">
+       <form id="manager" enctype="multipart/form-data" method="post" action="./?m=manager<?php echo $form_action; ?>">
+               <div id="manager-top">
+                       <div class="logo manager-images"><?php _e("Manager"); ?></div>
+                       
+                       <div class="meta">
+                               <span><?php echo(htmlspecialchars($user_meta)); ?></span>
+                               
+                               <?php if($id != 0) {
+                               
+                                       // Keep get
+                                       $keep_get = keepGet('(a|p|b|s|k)', false);
+                               
+                               ?>
+                                       <a class="logout manager-images" href="./?a=logout<?php echo $keep_get; ?>"><?php _e("Disconnect"); ?></a>
+                               <?php } ?>
+                               
+                               <a class="close manager-images" href="./<?php echo keepGet('(m|a|p|b|s|k)', true); ?>"><?php _e("Close"); ?></a>
+                       </div>
+                       
+                       <div class="clear"></div>
+               </div>
+               
+               <?php if($id != 0) { ?>
+                       <div id="manager-tabs">
+                               <a<?php currentTab('statistics', $page_identifier); ?> href="./?a=statistics<?php echo $keep_get; ?>"><?php _e("Statistics"); ?></a>
+                               <a<?php currentTab('configuration', $page_identifier); ?> href="./?a=configuration<?php echo $keep_get; ?>"><?php _e("Configuration"); ?></a>
+                               <a<?php currentTab('hosts', $page_identifier); ?> href="./?a=hosts<?php echo $keep_get; ?>"><?php _e("Hosts"); ?></a>
+                               <a<?php currentTab('storage', $page_identifier); ?> href="./?a=storage<?php echo $keep_get; ?>"><?php _e("Storage"); ?></a>
+                               <a<?php currentTab('design', $page_identifier); ?> href="./?a=design<?php echo $keep_get; ?>"><?php _e("Design"); ?></a>
+                               <a<?php currentTab('users', $page_identifier); ?> href="./?a=users<?php echo $keep_get; ?>"><?php _e("Users"); ?></a>
+                               <a<?php currentTab('updates', $page_identifier); ?> class="last" href="./?a=updates<?php echo $keep_get; ?>"><?php _e("Updates"); ?></a>
+                       </div>
+               <?php } ?>
+               
+               <div id="manager-content">
+                       <?php
+                       
+                       if($id != 0) {
+                               if(!storageWritable()) { ?>
+                                       <p class="info bottomspace fail"><?php _e("Your storage folders are not writable, please apply the good rights!"); ?></p>
+                               <?php }
+                               
+                               if(BOSHProxy() && extension_loaded('suhosin') && (ini_get('suhosin.get.max_value_length') < 1000000)) { ?>
+                                       <p class="info bottomspace neutral"><?php printf(T_("%1s may cause problems to the proxy, please increase %2s value up to %3s!"), 'Suhosin', '<em>suhosin.get.max_value_length</em>', '1000000'); ?></p>
+                               <?php }
+                               
+                               if(newUpdates($check_updates)) { ?>
+                                       <a class="info bottomspace neutral" href="./?a=updates<?php echo $keep_get; ?>"><?php _e("A new Jappix version is available! Check what is new and launch the update!"); ?></a>
+                               <?php }
+                       }
+                       
+                       // Authorized and statistics page requested
+                       if($id == 1) { ?>
+                               <h3 class="statistics manager-images"><?php _e("Statistics"); ?></h3>
+                               
+                               <p><?php _e("Basic statistics are processed by Jappix about some important things, you can find them below."); ?></p>
+                               
+                               <h4><?php _e("Access statistics"); ?></h4>
+                               
+                               <?php
+                               
+                               // Read the visits values
+                               $visits = getVisits();
+                               
+                               ?>
+                               
+                               <ul class="stats">
+                                       <li class="total"><b><?php _e("Total"); ?></b><span><?php echo $visits['total']; ?></span></li>
+                                       <li><b><?php _e("Daily"); ?></b><span><?php echo $visits['daily']; ?></span></li>
+                                       <li><b><?php _e("Weekly"); ?></b><span><?php echo $visits['weekly']; ?></span></li>
+                                       <li><b><?php _e("Monthly"); ?></b><span><?php echo $visits['monthly']; ?></span></li>
+                                       <li><b><?php _e("Yearly"); ?></b><span><?php echo $visits['yearly']; ?></span></li>
+                               </ul>
+                               
+                               <object class="stats" type="image/svg+xml" data="./php/stats-svg.php?l=<?php echo $locale; ?>&amp;g=access"></object>
+                               
+                               <?php
+                               
+                               // Get the share stats
+                               $share_stats = shareStats();
+                               
+                               // Any share stats to display?
+                               if(count($share_stats)) { ?>
+                                       <h4><?php _e("Share statistics"); ?></h4>
+                                       
+                                       <ol class="stats">
+                                               <?php
+                                               
+                                               // Display the users who have the largest share folder
+                                               $share_users = largestShare($share_stats, 8);
+                                               
+                                               foreach($share_users as $current_user => $current_value)
+                                                       echo('<li><b><a href="xmpp:'.$current_user.'">'.$current_user.'</a></b><span>'.formatBytes($current_value).'</span></li>');
+                                               
+                                               ?>
+                                       </ol>
+                                       
+                                       <object class="stats" type="image/svg+xml" data="./php/stats-svg.php?l=<?php echo $locale; ?>&amp;g=share"></object>
+                               <?php } ?>
+                               
+                               <h4><?php _e("Other statistics"); ?></h4>
+                               
+                               <ul class="stats">
+                                       <li class="total"><b><?php _e("Total"); ?></b><span><?php echo formatBytes(sizeDir(JAPPIX_BASE.'/store/')); ?></span></li>
+                                       
+                                       <?php
+                                       
+                                       // Append the human-readable array values
+                                       $others_stats = otherStats();
+                                       
+                                       foreach($others_stats as $others_name => $others_value)
+                                               echo('<li><b>'.$others_name.'</b><span>'.formatBytes($others_value).'</span></li>');
+                                       
+                                       ?>
+                               </ul>
+                               
+                               <object class="stats" type="image/svg+xml" data="./php/stats-svg.php?l=<?php echo $locale; ?>&amp;g=others"></object>
+                       <?php }
+                       
+                       // Authorized and configuration page requested
+                       else if($id == 2) { ?>
+                               <h3 class="configuration manager-images"><?php _e("Configuration"); ?></h3>
+                               
+                               <p><?php _e("Change your Jappix node configuration with this tool."); ?></p>
+                               
+                               <p><?php _e("Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."); ?></p>
+                               
+                               <?php
+                               
+                               // Define the main configuration variables
+                               include(JAPPIX_BASE.'/php/vars-main.php');
+                               
+                               // Read the main configuration POST
+                               if(isset($_POST['save'])) {
+                                       include(JAPPIX_BASE.'/php/post-main.php');
+                                       
+                                       // Show a success alert
+                                       ?>
+                                               <p class="info smallspace success"><?php _e("Changes saved!"); ?></p>
+                                       <?php
+                               }
+                               
+                               // Include the main configuration form
+                               include(JAPPIX_BASE.'/php/form-main.php');
+                       }
+                       
+                       // Authorized and hosts page requested
+                       else if($id == 3) { ?>
+                               <h3 class="hosts manager-images"><?php _e("Hosts"); ?></h3>
+                               
+                               <p><?php _e("Change the XMPP hosts that this Jappix node serve with this tool."); ?></p>
+                               
+                               <p><?php _e("Maybe you don't know what a BOSH server is? In fact, this is a relay between a Jappix client and a XMPP server, which is necessary because of technical limitations."); ?></p>
+                               
+                               <p><?php _e("Note that if you don't specify a value which is compulsory, it will be automatically completed with the default one."); ?></p>
+                               
+                               <?php
+                               
+                               // Define the hosts configuration variables
+                               include(JAPPIX_BASE.'/php/vars-hosts.php');
+                               
+                               // Read the hosts configuration POST
+                               if(isset($_POST['save'])) {
+                                       include(JAPPIX_BASE.'/php/post-hosts.php');
+                                       
+                                       // Show a success alert
+                                       ?>
+                                               <p class="info smallspace success"><?php _e("Changes saved!"); ?></p>
+                                       <?php
+                               }
+                               
+                               // Include the hosts configuration form
+                               include(JAPPIX_BASE.'/php/form-hosts.php');
+                       }
+                       
+                       // Authorized and storage page requested
+                       else if($id == 4) { ?>
+                               <h3 class="storage manager-images"><?php _e("Storage"); ?></h3>
+                               
+                               <p><?php _e("All this Jappix node stored files can be managed with this tool: please select a sub-folder and start editing its content!"); ?></p>
+                               
+                               <?php
+                               
+                                       // Include the store configuration vars
+                                       include(JAPPIX_BASE.'/php/vars-store.php');
+                                       
+                                       // Include the store configuration POST handler
+                                       include(JAPPIX_BASE.'/php/post-store.php');
+                                       
+                                       // Include the store configuration GET handler
+                                       include(JAPPIX_BASE.'/php/get-store.php');
+                                       
+                               ?>
+                               
+                               <h4><?php _e("Maintenance"); ?></h4>
+                               
+                               <p><?php _e("Keep your Jappix node fresh and fast, clean the storage folders regularly!"); ?></p>
+                               
+                               <?php
+                               
+                                       // Keep get
+                                       $keep_get = keepGet('p', false);
+                               
+                               ?>
+                               
+                               <ul>
+                                       <li class="total"><a href="./?p=everything<?php echo $keep_get; ?>"><?php _e("Clean everything"); ?></a></li>
+                                       <li><a href="./?p=cache<?php echo $keep_get; ?>"><?php _e("Purge cache"); ?></a></li>
+                                       <li><a href="./?p=logs<?php echo $keep_get; ?>"><?php _e("Purge logs"); ?></a></li>
+                                       <li><a href="./?p=send<?php echo $keep_get; ?>"><?php _e("Purge sent files"); ?></a></li>
+                                       <li><a href="./?p=updates<?php echo $keep_get; ?>"><?php _e("Purge updates"); ?></a></li>
+                               </ul>
+                               
+                               <h4><?php _e("Share"); ?></h4>
+                               
+                               <p><?php _e("Stay tuned in what your users store on your server and remove undesired content with this tool."); ?></p>
+                               
+                               <fieldset>
+                                       <legend><?php _e("Browse"); ?></legend>
+                                       
+                                       <div class="browse">
+                                               <?php
+                                               
+                                               // List the share files
+                                               browseFolder($share_folder, 'share');
+                                               
+                                               ?>
+                                       </div>
+                               </fieldset>
+                               
+                               <h4><?php _e("Music"); ?></h4>
+                               
+                               <p><?php _e("Upload your music (Ogg Vorbis, MP3 or WAV) to be able to listen to it in Jappix!"); ?></p>
+                               
+                               <p><?php printf(T_("The file you want to upload must be smaller than %s."), formatBytes(uploadMaxSize()).''); ?></p>
+                               
+                               <fieldset>
+                                       <legend><?php _e("New"); ?></legend>
+                                       
+                                       <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo(uploadMaxSize().''); ?>">
+                                       
+                                       <label for="music_title"><?php _e("Title"); ?></label><input id="music_title" class="icon manager-images" type="text" name="music_title" value="<?php echo(htmlspecialchars($music_title)); ?>" />
+                                       
+                                       <label for="music_artist"><?php _e("Artist"); ?></label><input id="music_artist" class="icon manager-images" type="text" name="music_artist" value="<?php echo(htmlspecialchars($music_artist)); ?>" />
+                                       
+                                       <label for="music_album"><?php _e("Album"); ?></label><input id="music_album" class="icon manager-images" type="text" name="music_album" value="<?php echo(htmlspecialchars($music_album)); ?>" />
+                                       
+                                       <label for="music_file"><?php _e("File"); ?></label><input id="music_file" type="file" name="music_file" accept="audio/*" />
+                                       <label for="music_upload"><?php _e("Upload"); ?></label><input id="music_upload" type="submit" name="upload" value="<?php _e("Upload"); ?>" />
+                               </fieldset>
+                               
+                               <fieldset>
+                                       <legend><?php _e("Browse"); ?></legend>
+                                       
+                                       <div class="browse">
+                                               <?php
+                                               
+                                               // List the music files
+                                               browseFolder($music_folder, 'music');
+                                               
+                                               ?>
+                                       </div>
+                               </fieldset>
+                       <?php }
+                       
+                       // Authorized and design page requested
+                       else if($id == 5) { ?>
+                               <h3 class="design manager-images"><?php _e("Design"); ?></h3>
+                               
+                               <p><?php _e("Jappix is fully customisable: you can change its design right here."); ?></p>
+                               
+                               <?php
+                               
+                                       // Include the design configuration vars
+                                       include(JAPPIX_BASE.'/php/vars-design.php');
+                                       
+                                       // Include the design configuration POST handler
+                                       include(JAPPIX_BASE.'/php/post-design.php');
+                                       
+                                       // Include the design configuration reader
+                                       include(JAPPIX_BASE.'/php/read-design.php');
+                                       
+                                       // Folder view?
+                                       if(isset($_GET['b']) && isset($_GET['s']) && ($_GET['b'] == 'backgrounds'))
+                                               $backgrounds_folder = urldecode($_GET['s']);
+                               
+                               ?>
+                               
+                               <h4><?php _e("Logo"); ?></h4>
+                               
+                               <p><?php _e("You can set your own service logo to replace the default one. Take care of the size and the main color of each logo!"); ?></p>
+                               
+                               <div class="sub">
+                                       <p><?php _e("Upload each logo with the recommended maximum pixel size."); ?></p>
+                                       <p><?php _e("Your logo format must be PNG. Leave a field empty and the logo will not be changed."); ?></p>                                      
+                                       
+                                       <label for="logo_own_1_location">Jappix Desktop, <em>311×113</em></label><?php logoFormField('1', 'desktop_home'); ?>
+                                       <label for="logo_own_2_location">Jappix Desktop, <em>90×25</em></label><?php logoFormField('2', 'desktop_app'); ?>
+                                       <label for="logo_own_3_location">Jappix Mobile, <em>83×30</em></label><?php logoFormField('3', 'mobile'); ?>
+                                       <label for="logo_own_4_location">Jappix Mini, <em>81×22</em></label><?php logoFormField('4', 'mini'); ?>
+                                       
+                                       <label for="logo_own_upload"><?php _e("Upload"); ?></label><input id="logo_own_upload" type="submit" name="logo_upload" value="<?php _e("Upload"); ?>" />
+                                       
+                                       <div class="clear"></div>
+                               </div>
+                               
+                               <h4><?php _e("Background"); ?></h4>
+                               
+                               <p><?php _e("Change your Jappix node background with this tool. You can either set a custom color or an uploaded image. Let your creativity flow!"); ?></p>
+                               
+                               <label class="master" for="background_default"><input id="background_default" type="radio" name="background_type" value="default"<?php echo($background_default); ?> /><?php _e("Use default background"); ?></label>
+                               
+                               <?php if($backgrounds_number) { ?>
+                                       <label class="master" for="background_image"><input id="background_image" type="radio" name="background_type" value="image"<?php echo($background_image); ?> /><?php _e("Use your own image"); ?></label>
+                               
+                                       <div class="sub">
+                                               <p><?php _e("Select a background to use and change the display options."); ?></p>
+                                               
+                                               <label for="background_image_file"><?php _e("Image"); ?></label><select id="background_image_file" name="background_image_file">
+                                                       <?php
+                                                       
+                                                               // List the background files
+                                                               foreach($backgrounds as $backgrounds_current) {
+                                                                       // Check this is the selected background
+                                                                       if($backgrounds_current == $background['image_file'])
+                                                                               $backgrounds_selected = ' selected=""';
+                                                                       else
+                                                                               $backgrounds_selected = '';
+                                                                       
+                                                                       // Encode the current background name
+                                                                       $backgrounds_current = htmlspecialchars($backgrounds_current);
+                                                                       
+                                                                       echo('<option value="'.$backgrounds_current.'"'.$backgrounds_selected.'>'.$backgrounds_current.'</option>');
+                                                               }
+                                                       
+                                                       ?>
+                                               </select>
+                                               
+                                               <label for="background_image_repeat"><?php _e("Repeat"); ?></label><select id="background_image_repeat" name="background_image_repeat">
+                                                       <option value="no-repeat"<?php echo($background_image_repeat_no); ?>><?php _e("No"); ?></option>
+                                                       <option value="repeat"<?php echo($background_image_repeat_all); ?>><?php _e("All"); ?></option>
+                                                       <option value="repeat-x"<?php echo($background_image_repeat_x); ?>><?php _e("Horizontal"); ?></option>
+                                                       <option value="repeat-y"<?php echo($background_image_repeat_y); ?>><?php _e("Vertical"); ?></option>
+                                               </select>
+                                               
+                                               <label for="background_image_horizontal"><?php _e("Horizontal"); ?></label><select id="background_image_horizontal" name="background_image_horizontal">
+                                                       <option value="center"<?php echo($background_image_horizontal_center); ?>><?php _e("Center"); ?></option>
+                                                       <option value="left"<?php echo($background_image_horizontal_left); ?>><?php _e("Left"); ?></option>
+                                                       <option value="right"<?php echo($background_image_horizontal_right); ?>><?php _e("Right"); ?></option>
+                                               </select>
+                                               
+                                               <label for="background_image_vertical"><?php _e("Vertical"); ?></label><select id="background_image_vertical" name="background_image_vertical">
+                                                       <option value="center"<?php echo($background_image_vertical_center); ?>><?php _e("Center"); ?></option>
+                                                       <option value="top"<?php echo($background_image_vertical_top); ?>><?php _e("Top"); ?></option>
+                                                       <option value="bottom"<?php echo($background_image_vertical_bottom); ?>><?php _e("Bottom"); ?></option>
+                                               </select>
+                                               
+                                               <label for="background_image_adapt"><?php _e("Adapt"); ?></label><input id="background_image_adapt" type="checkbox" name="background_image_adapt"<?php echo($background_image_adapt); ?> />
+                                               
+                                               <label for="background_image_color"><?php _e("Color"); ?></label><input id="background_image_color" class="icon manager-images" type="color" name="background_image_color" value="<?php echo(htmlspecialchars($background['image_color'])); ?>" />
+                                               
+                                               <div class="clear"></div>
+                                       </div>
+                               <?php } ?>
+                               
+                               <label class="master" for="background_color"><input id="background_color" type="radio" name="background_type" value="color"<?php echo($background_color); ?> /><?php _e("Use your own color"); ?></label>
+                               
+                               <div class="sub">
+                                       <p><?php _e("Type the hexadecimal color value you want to use as a background."); ?></p>
+                                       
+                                       <label for="background_color_color"><?php _e("Color"); ?></label><input id="background_color_color" class="icon manager-images" type="color" name="background_color_color" value="<?php echo(htmlspecialchars($background['color_color'])); ?>" />
+                                       
+                                       <div class="clear"></div>
+                               </div>
+                               
+                               <h4><?php _e("Manage backgrounds"); ?></h4>
+                               
+                               <p><?php _e("You can add a new background to the list with this tool. Please send a valid image."); ?></p>
+                               
+                               <div class="sub">
+                                       <p><?php printf(T_("The file you want to upload must be smaller than %s."), formatBytes(uploadMaxSize()).''); ?></p>
+                                       
+                                       <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo(uploadMaxSize().''); ?>">
+                                       
+                                       <label for="background_image_location"><?php _e("File"); ?></label><input id="background_image_location" type="file" name="background_image_upload" accept="image/*" />
+                                       <label for="background_image_upload"><?php _e("Upload"); ?></label><input id="background_image_upload" type="submit" name="background_upload" value="<?php _e("Upload"); ?>" />
+                                       
+                                       <div class="clear"></div>
+                               </div>
+                               
+                               <p><?php _e("If you want to remove some backgrounds, use the browser below."); ?></p>
+                               
+                               <fieldset>
+                                       <legend><?php _e("List"); ?></legend>
+                                       
+                                       <div class="browse">
+                                               <?php
+                                               
+                                               // List the background files
+                                               browseFolder($backgrounds_folder, 'backgrounds');
+                                               
+                                               ?>
+                                       </div>
+                               </fieldset>
+                               
+                               <h4><?php _e("Notice"); ?></h4>
+                               
+                               <p><?php _e("Define a homepage notice for all your users, such as a warn, an important message or an advert with this tool."); ?></p>
+                               
+                               <label class="master" for="notice_none"><input id="notice_none" type="radio" name="notice_type" value="none"<?php echo($notice_none); ?> /><?php _e("None"); ?></label>
+                               
+                               <label class="master" for="notice_simple"><input id="notice_simple" type="radio" name="notice_type" value="simple"<?php echo($notice_simple); ?> /><?php _e("Simple notice"); ?></label>
+                               
+                               <div class="sub">
+                                       <p><?php _e("This notice only needs simple text to be displayed, but no code is allowed!"); ?></p>
+                               </div>
+                               
+                               <label class="master" for="notice_advanced"><input id="notice_advanced" type="radio" name="notice_type" value="advanced"<?php echo($notice_advanced); ?> /><?php _e("Advanced notice"); ?></label>
+                               
+                               <div class="sub">
+                                       <p><?php _e("You can customize your notice with embedded HTML, CSS and JavaScript, but you need to code the style."); ?></p>
+                               </div>
+                               
+                               <div class="clear"></div>
+                               
+                               <textarea class="notice-text" name="notice_text" rows="8" cols="60"><?php echo(htmlspecialchars($notice_text)); ?></textarea>
+                       <?php }
+                       
+                       // Authorized and users page requested
+                       else if($id == 6) { ?>
+                               <h3 class="users manager-images"><?php _e("Users"); ?></h3>
+                               
+                               <p><?php _e("You can define more than one administrator for this Jappix node. You can also change a password with this tool."); ?></p>
+                               
+                               <?php
+                               
+                               // Add an user?
+                               if(isset($_POST['add'])) {
+                                       // Include the users POST handler
+                                       include(JAPPIX_BASE.'/php/post-users.php');
+                                       
+                                       if($valid_user) { ?>
+                                               <p class="info smallspace success"><?php _e("The user has been added!"); ?></p>
+                                       <?php }
+                                       
+                                       else { ?>
+                                               <p class="info smallspace fail"><?php _e("Oops, you missed something or the two passwords do not match!"); ?></p>
+                               <?php }
+                               }
+                               
+                               // Remove an user?
+                               else if(isset($_POST['remove'])) {
+                                       // Initialize the match
+                                       $users_removed = false;
+                                       $users_remove = array();
+                                       
+                                       // Try to get the users to remove
+                                       foreach($_POST as $post_key => $post_value) {
+                                               // Is it an admin user?
+                                               if(preg_match('/^admin_(.+)$/i', $post_key)) {
+                                                       // Update the marker
+                                                       $users_removed = true;
+                                                       
+                                                       // Push the value to the global array
+                                                       array_push($users_remove, $post_value);
+                                               }
+                                       }
+                                       
+                                       // Somebody has been removed
+                                       if($users_removed) {
+                                       
+                                               // Remove the users!
+                                               manageUsers('remove', $users_remove);
+                                       
+                                       ?>
+                                               <p class="info smallspace success"><?php _e("The chosen users have been removed."); ?></p>
+                                       <?php }
+                                       
+                                       // Nobody has been removed
+                                       else { ?>
+                                               <p class="info smallspace fail"><?php _e("You must select one or more users to be removed!"); ?></p>
+                               <?php }
+                               } ?>
+                               
+                               <h4><?php _e("Add"); ?></h4>
+                               
+                               <p><?php _e("Add a new user with this tool, or change a password (type an existing username). Please submit a strong password!"); ?></p>
+                               
+                               <?php
+                               
+                               // Include the user add form
+                               include(JAPPIX_BASE.'/php/form-users.php');
+                               
+                               ?>
+                               
+                               <h4><?php _e("Manage"); ?></h4>
+                               
+                               <p><?php _e("Remove users with this tool. Note that you cannot remove an user if he is the only one remaining."); ?></p>
+                               
+                               <fieldset>
+                                       <legend><?php _e("List"); ?></legend>
+                                       
+                                       <div class="browse">
+                                               <?php
+                                               
+                                               // List the users
+                                               browseUsers();
+                                               
+                                               ?>
+                                       </div>
+                               </fieldset>
+                       <?php }
+                       
+                       // Authorized and updates page requested
+                       else if($id == 7) { ?>
+                               <h3 class="updates manager-images"><?php _e("Updates"); ?></h3>
+                               
+                               <p><?php _e("Update your Jappix node with this tool, or check if a new one is available. Informations about the latest version are also displayed (in english)."); ?></p>
+                               
+                               <?php
+                               
+                               // Using developer mode (no need to update)?
+                               if(isDeveloper()) { ?>
+                                       <h4><?php _e("Check for updates"); ?></h4>
+                                       
+                                       <p class="info smallspace neutral"><?php printf(T_("You are using a development version of Jappix. Update it through our repository by executing: %s."), '<em>svn up</em>'); ?></p>
+                               <?php }
+                               
+                               // New updates available?
+                               else if(newUpdates($check_updates)) {
+                                       // Get the update informations
+                                       $update_infos = updateInformations();
+                                       
+                                       // We can launch the update!
+                                       if(isset($_GET['p']) && ($_GET['p'] == 'update')) { ?>
+                                               <h4><?php _e("Update in progress"); ?></h4>
+                                               
+                                               <?php if(processUpdate($update_infos['url'])) { ?>
+                                                       <p class="info smallspace success"><?php _e("Jappix has been updated: you are now running the latest version. Have fun!"); ?></p>
+                                               <?php } else { ?>
+                                                       <p class="info smallspace fail"><?php _e("The update has failed! Please try again later."); ?></p>
+                                               <?php }
+                                       }
+                                       
+                                       // We just show a notice
+                                       else {
+                               ?>
+                                               <h4><?php _e("Available updates"); ?></h4>
+                                               
+                                               <a class="info smallspace fail" href="./?p=update<?php echo keepGet('(p|b|s)', false); ?>"><?php printf(T_("Your version is out to date. Update it now to %s by clicking here!"), '<em>'.$update_infos['id'].'</em>'); ?></a>
+                                               
+                                               <h4><?php _e("What's new?"); ?></h4>
+                                               
+                                               <div><?php echo $update_infos['description']; ?></div>
+                               <?php }
+                               
+                               // No new update
+                               } else { ?>
+                                       <h4><?php _e("Check for updates"); ?></h4>
+                                       
+                                       <a class="info smallspace success" href="./?p=check<?php echo keepGet('(p|b|s)', false); ?>"><?php _e("Your version seems to be up to date, but you can check updates manually by clicking here."); ?></a>
+                               <?php } ?>
+                       <?php }
+                       
+                       // Not authorized, show the login form
+                       else { ?>
+                               <h3 class="login manager-images"><?php _e("Manager access"); ?></h3>
+                               
+                               <p><?php _e("This is a restricted area: only the authorized users can manage this Jappix node."); ?></p>
+                               <p><?php _e("Please use the form below to login to the administration panel."); ?></p>
+                               <p><?php _e("To improve security, sessions are limited in time and when your browser will be closed, you will be logged out."); ?></p>
+                               
+                               <fieldset>
+                                       <legend><?php _e("Credentials"); ?></legend>
+                                       
+                                       <label for="admin_name"><?php _e("User"); ?></label><input id="admin_name" class="icon manager-images" type="text" name="admin_name" value="<?php echo(htmlspecialchars($user)); ?>" required="" />
+                                       
+                                       <label for="admin_password"><?php _e("Password"); ?></label><input id="admin_password" class="icon manager-images" type="password" name="admin_password" required="" />
+                               </fieldset>
+                               
+                               <?php
+                               
+                               // Disconnected
+                               if($logout_fired) { ?>
+                                       <p class="info bigspace success"><?php _e("You have been logged out. Goodbye!"); ?></p>
+                               <?php }
+                               
+                               // Login error
+                               else if($login_fired) { ?>
+                                       <p class="info bigspace fail"><?php _e("Oops, you could not be recognized as a valid administrator. Check your credentials!"); ?></p>
+                               <?php
+                               
+                                       // Remove the session
+                                       unset($_SESSION['jappix_user']);
+                                       unset($_SESSION['jappix_password']);
+                               
+                               }
+                       } ?>
+                       
+                       <div class="clear"></div>
+               </div>
+               
+               <div id="manager-buttons">
+                       <?php if($id == 0) { ?>
+                               <input type="submit" name="login" value="<?php _e("Here we go!"); ?>" />
+                       <?php } else { ?>
+                               <?php } if($add_button) { ?>
+                                       <input type="submit" name="add" value="<?php _e("Add"); ?>" />
+                               <?php } if($save_button) { ?>
+                                       <input type="submit" name="save" value="<?php _e("Save"); ?>" />
+                               <?php } if($remove_button) { ?>
+                                       <input type="submit" name="remove" value="<?php _e("Remove"); ?>" />
+                       <?php } ?>
+                       
+                       <div class="clear"></div>
+               </div>
+               
+       </form>
+</body>
+
+</html>
+
+<!-- Jappix Manager <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/mobile-detect.php b/jappixmini/jappix/php/mobile-detect.php
new file mode 100644 (file)
index 0000000..5f2b450
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * Mobile Detect
+ *
+ * @license    http://www.opensource.org/licenses/mit-license.php The MIT License
+ * @version    SVN: $Id: Mobile_Detect.php 3 2009-05-21 13:06:28Z vic.stanciu $
+ */
+
+/**
+ * MODIFIED FOR THE JAPPIX PROJECT
+ * Last revision: 20/11/10
+ *
+ * Thanks to LinkMauve for his patch!
+ */
+
+class Mobile_Detect {
+    
+    protected $accept;
+    protected $userAgent;
+    
+    protected $isMobile     = false;
+    protected $isAndroid    = null;
+    protected $isIphone     = null;
+    protected $isBlackberry = null;
+    protected $isOpera      = null;
+    protected $isPalm       = null;
+    protected $isWindows    = null;
+    protected $isGeneric    = null;
+
+    protected $devices = array(
+        "android"       => "android",
+        "blackberry"    => "blackberry",
+        "iphone"        => "(iphone|ipod)",
+        "opera"         => "opera mini",
+        "palm"          => "(avantgo|blazer|elaine|hiptop|palm|plucker|xiino)",
+        "windows"       => "windows ce; (iemobile|ppc|smartphone)",
+        "generic"       => "(kindle|mobile|mmp|midp|o2|pda|pocket|psp|symbian|smartphone|treo|up.browser|up.link|vodafone|wap)"
+    );
+
+
+    public function __construct() {
+        $this->userAgent = $_SERVER['HTTP_USER_AGENT'];
+
+       if (isset($_SERVER['HTTP_ACCEPT']))
+               $this->accept = $_SERVER['HTTP_ACCEPT'];
+       else
+               $this->accept = '';
+
+        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])|| isset($_SERVER['HTTP_PROFILE'])) {
+            $this->isMobile = true;
+        } elseif (strpos($this->accept,'text/vnd.wap.wml') > 0 || strpos($this->accept,'application/vnd.wap.xhtml+xml') > 0) {
+            $this->isMobile = true;
+        } else {
+            foreach ($this->devices as $device => $regexp) {
+                if ($this->isDevice($device)) {
+                    $this->isMobile = true;
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Overloads isAndroid() | isBlackberry() | isOpera() | isPalm() | isWindows() | isGeneric() through isDevice()
+     *
+     * @param string $name
+     * @param array $arguments
+     * @return bool
+     */
+    public function __call($name, $arguments) {
+        $device = substr($name, 2);
+        if ($name == "is" . ucfirst($device)) {
+            return $this->isDevice($device);
+        } else {
+            trigger_error("Method $name not defined", E_USER_ERROR);
+        }
+    }
+
+
+    /**
+     * Returns true if any type of mobile device detected, including special ones
+     * @return bool
+     */
+    public function isMobile() {
+        return $this->isMobile;
+    }
+
+
+    protected function isDevice($device) {
+        $var    = "is" . ucfirst($device);
+        $return = $this->$var === null ? (bool) preg_match("/" . $this->devices[$device] . "/i", $this->userAgent) : $this->$var;
+
+        if ($device != 'generic' && $return == true) {
+            $this->isGeneric = false;
+        }
+
+        return $return;
+    }
+}
diff --git a/jappixmini/jappix/php/mobile.php b/jappixmini/jappix/php/mobile.php
new file mode 100644 (file)
index 0000000..1f0f0fe
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Mobile PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 10/07/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <meta content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" name="viewport">
+       <title><?php _e("Jappix Mobile"); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+       <?php echoGetFiles($hash, '', 'css', 'mobile.xml', ''); echo "\n"; ?>
+       <?php echoGetFiles($hash, $locale, 'js', 'mobile.xml', ''); echo "\n"; ?>
+</head>
+
+<body>
+       <div id="home">
+               <div class="header">
+                       <div class="mobile-images"></div>
+               </div>
+               
+               <noscript>
+                       <div class="notification" id="noscript">
+                               <?php _e("Please enable JavaScript"); ?>
+                       </div>
+               </noscript>
+               
+               <div class="notification" id="error">
+                       <?php _e("Error"); ?>
+               </div>
+               
+               <div class="notification" id="info">
+                       <?php _e("Please wait..."); ?>
+               </div>
+               
+               <div class="login">
+                       <?php _e("Login"); ?>
+                       
+                       <form action="#" method="post" onsubmit="return doLogin(this);">
+                               <input class="xid mobile-images" type="text" name="xid" required="" />
+                               <input class="password mobile-images" type="password" id="pwd" name="pwd" required="" />
+                               <?php if(REGISTRATION != 'off') { ?>
+                               <label><input class="register" type="checkbox" id="reg" name="reg" /><?php _e("Register"); ?></label>
+                               <?php } ?>
+                               <input type="submit" name="ok" value="<?php _e("Here we go!"); ?>" />
+                       </form>
+               </div>
+               
+               <a href="./?m=desktop<?php echo keepGet('m', false); ?>"><?php _e("Desktop"); ?></a>
+       </div>
+</body>
+
+</html>
+
+<!-- Jappix Mobile <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/music-search.php b/jappixmini/jappix/php/music-search.php
new file mode 100644 (file)
index 0000000..b284972
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix music search script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 15/01/12
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic() || isUpload())
+       exit;
+
+// If valid data was sent
+if((isset($_GET['searchquery']) && !empty($_GET['searchquery'])) && (isset($_GET['location']) && !empty($_GET['location']))) {
+       // Set a XML header
+       header('Content-Type: text/xml; charset=utf-8');
+       
+       // Get the values
+       $searchquery = $_GET['searchquery'];
+       $location = $_GET['location'];
+       
+       // Jamendo search?
+       if($location == 'jamendo')
+               exit(read_url('http://api.jamendo.com/get2/name+id+duration+url/track/xml/?searchquery='.urlencode($searchquery).'&order=searchweight_desc'));
+       
+       // Local music search
+       $xml = '<data>';
+       $searchquery = strtolower($searchquery);
+       
+       // Escape the regex special characters
+       $searchquery = escapeRegex($searchquery);
+       
+       // Search in the directory
+       $repertory = '../store/music/';
+       $scan = scandir($repertory);
+       
+       foreach($scan as $current) {
+               // This file match our query!
+               if(is_file($repertory.$current) && $current && preg_match('/(^|\s|\[)('.$searchquery.')(.+)?(\.(og(g|a)|mp3|wav))$/i', strtolower($current))) {
+                       // Get the basic informations
+                       $title = preg_replace('/^(.+)(\.)(og(g|a)|mp3|wav)$/i', '$1', $current);
+                       $url = $location.'store/music/'.$current;
+                       $ext = getFileExt($current);
+                       $id = md5($url);
+                       
+                       // Get the MIME type
+                       if($ext == 'mp3')
+                               $type = 'audio/mpeg';
+                       else if($ext == 'wav')
+                               $type = 'audio/x-wav';
+                       else
+                               $type = 'audio/ogg';
+                       
+                       // Get the advanced informations
+                       $locked_title = $title;
+                       $artist = '';
+                       $source = '';
+                       
+                       $title_regex = '/^(([^-]+) - )?([^\[]+)( \[(.+))?$/i';
+                       $artist_regex = '/^(.+) - (.+)$/i';
+                       $source_regex = '/^(.+) \[(.+)\]$/i';
+                       
+                       if(preg_match($title_regex, $locked_title))
+                               $title = preg_replace($title_regex, '$3', $locked_title);
+                       
+                       if(preg_match($artist_regex, $locked_title))
+                               $artist = preg_replace($artist_regex, '$1', $locked_title);
+                       
+                       if(preg_match($source_regex, $locked_title))
+                               $source = preg_replace($source_regex, '$2', $locked_title);
+                       
+                       // Generate the XML
+                       $xml .= '<data><track><name>'.htmlspecialchars($title).'</name><artist>'.htmlspecialchars($artist).'</artist><source>'.htmlspecialchars($source).'</source><id>'.htmlspecialchars($id).'</id><url>'.htmlspecialchars($url).'</url><type>'.$type.'</type></track></data>';
+               }
+       }
+       
+       // End
+       $xml .= '</data>';
+       
+       // Return the path to the file
+       exit($xml);
+}
+
+?>
diff --git a/jappixmini/jappix/php/post-design.php b/jappixmini/jappix/php/post-design.php
new file mode 100644 (file)
index 0000000..030fd68
--- /dev/null
@@ -0,0 +1,215 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the design configuration POST handler (manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 25/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Handle the remove GET
+if(isset($_GET['k']) && !empty($_GET['k'])) {
+       $kill_logo = JAPPIX_BASE.'/store/logos/'.$_GET['k'].'.png';
+       
+       if(isSafe($kill_logo) && file_exists($kill_logo)) {
+               unlink($kill_logo);
+               
+               echo('<p class="info smallspace success">'.T_("The selected elements have been removed.").'</p>');
+       }
+}
+
+// Handle the remove POST
+else if(isset($_POST['remove']))
+       removeElements();
+
+// Handle the logo upload POST
+else if(isset($_POST['logo_upload'])) {
+       // Avoid errors
+       $logos_arr_1_name = $logos_arr_1_tmp = $logos_arr_2_name = $logos_arr_2_tmp = $logos_arr_3_name = $logos_arr_3_tmp = $logos_arr_4_name = $logos_arr_4_tmp = '';
+       
+       if(isset($_FILES['logo_own_1_location'])) {
+               $logos_arr_1_name = $_FILES['logo_own_1_location']['name'];
+               $logos_arr_1_tmp = $_FILES['logo_own_1_location']['tmp_name'];
+       }
+       
+       if(isset($_FILES['logo_own_2_location'])) {
+               $logos_arr_2_name = $_FILES['logo_own_2_location']['name'];
+               $logos_arr_2_tmp = $_FILES['logo_own_2_location']['tmp_name'];
+       }
+       
+       if(isset($_FILES['logo_own_3_location'])) {
+               $logos_arr_3_name = $_FILES['logo_own_3_location']['name'];
+               $logos_arr_3_tmp = $_FILES['logo_own_3_location']['tmp_name'];
+       }
+       
+       if(isset($_FILES['logo_own_4_location'])) {
+               $logos_arr_4_name = $_FILES['logo_own_4_location']['name'];
+               $logos_arr_4_tmp = $_FILES['logo_own_4_location']['tmp_name'];
+       }
+       
+       // File infos array
+       $logos = array(
+               array($logos_arr_1_name, $logos_arr_1_tmp, JAPPIX_BASE.'/store/logos/desktop_home.png'),
+               array($logos_arr_2_name, $logos_arr_2_tmp, JAPPIX_BASE.'/store/logos/desktop_app.png'),
+               array($logos_arr_3_name, $logos_arr_3_tmp, JAPPIX_BASE.'/store/logos/mobile.png'),
+               array($logos_arr_4_name, $logos_arr_4_tmp, JAPPIX_BASE.'/store/logos/mini.png')
+       );
+       
+       // Check for errors
+       $logo_error = false;
+       $logo_not_png = false;
+       $logo_anything = false;
+       
+       foreach($logos as $sub_array) {
+               // Nothing?
+               if(!$sub_array[0] || !$sub_array[1])
+                       continue;
+               
+               // Not an image?
+               if(getFileExt($sub_array[0]) != 'png') {
+                       $logo_not_png = true;
+                       
+                       continue;
+               }
+               
+               // Upload error?
+               if(!move_uploaded_file($sub_array[1], $sub_array[2])) {
+                       $logo_error = true;
+                       
+                       continue;
+               }
+               
+               $logo_anything = true;
+       }
+       
+       // Not an image?
+       if($logo_not_png) { ?>
+               <p class="info smallspace fail"><?php _e("This is not a valid image, please use the PNG format!"); ?></p>
+       <?php }
+       
+       // Upload error?
+       else if($logo_error || !$logo_anything) { ?>
+               <p class="info smallspace fail"><?php _e("The image could not be received, would you mind retry?"); ?></p>
+       <?php }
+       
+       // Everything went fine
+       else { ?>
+               <p class="info smallspace success"><?php _e("Your service logo has been successfully changed!"); ?></p>
+       <?php }
+}
+
+// Handle the background upload POST
+else if(isset($_POST['background_upload'])) {
+       // Get the file path
+       $name_background_image = $_FILES['background_image_upload']['name'];
+       $temp_background_image = $_FILES['background_image_upload']['tmp_name'];
+       $path_background_image = JAPPIX_BASE.'/store/backgrounds/'.$name_background_image;
+       
+       // An error occured?
+       if(!isSafe($name_background_image) || $_FILES['background_image_upload']['error'] || !move_uploaded_file($temp_background_image, $path_background_image)) { ?>
+       
+               <p class="info smallspace fail"><?php _e("The image could not be received, would you mind retry?"); ?></p>
+       
+       <?php }
+       
+       // Bad extension?
+       else if(!isImage($name_background_image)) {
+               // Remove the image file
+               if(file_exists($path_background_image))
+                       unlink($path_background_image); 
+       ?>
+       
+               <p class="info smallspace fail"><?php _e("This is not a valid image, please use PNG, GIF or JPG!"); ?></p>
+       
+       <?php }
+       
+       // The file has been sent
+       else { ?>
+       
+               <p class="info smallspace success"><?php _e("Your image was added to the list!"); ?></p>
+       
+       <?php }
+}
+
+// Handle the save POST
+else if(isset($_POST['save'])) {
+       // Marker
+       $save_marker = true;
+       
+       // Handle it for background
+       $background = array();
+       
+       if(isset($_POST['background_type']))
+               $background['type'] = $_POST['background_type'];
+       
+       if(isset($_POST['background_image_file']))
+               $background['image_file'] = $_POST['background_image_file'];
+
+       if(isset($_POST['background_image_repeat']))
+               $background['image_repeat'] = $_POST['background_image_repeat'];
+       
+       if(isset($_POST['background_image_horizontal']))
+               $background['image_horizontal'] = $_POST['background_image_horizontal'];
+       
+       if(isset($_POST['background_image_vertical']))
+               $background['image_vertical'] = $_POST['background_image_vertical'];
+       
+       if(isset($_POST['background_image_adapt']))
+               $background['image_adapt'] = 'on';
+       
+       if(isset($_POST['background_image_color']))
+               $background['image_color'] = $_POST['background_image_color'];
+       
+       if(isset($_POST['background_color_color']))
+               $background['color_color'] = $_POST['background_color_color'];
+       
+       // Write the configuration file
+       writeBackground($background);
+       
+       // Handle it for notice
+       if(isset($_POST['notice_type']))
+               $notice_type = $_POST['notice_type'];
+       else
+               $notice_type = 'none';
+       
+       $notice_text = '';
+       
+       if(isset($_POST['notice_text']))
+               $notice_text = $_POST['notice_text'];
+       
+       // Check our values
+       if(!$notice_text && ($notice_type != 'none'))
+               $save_marker = false;
+       
+       // All is okay
+       if($save_marker) {
+               // Write the notice configuration
+               writeNotice($notice_type, $notice_text);
+               
+               // Show a success notice
+               ?>
+               
+                       <p class="info smallspace success"><?php _e("Your design preferences have been saved!"); ?></p>
+               
+               <?php }
+               
+               // Something went wrong
+               else { ?>
+               
+                       <p class="info smallspace fail"><?php _e("Please check your inputs: something is missing!"); ?></p>
+               
+               <?php
+       }
+}
+
+?>
diff --git a/jappixmini/jappix/php/post-hosts.php b/jappixmini/jappix/php/post-hosts.php
new file mode 100644 (file)
index 0000000..ad1e74f
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the hosts configuration POST handler (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Main host
+if(isset($_POST['host_main']) && !empty($_POST['host_main']))
+       $host_main = stripslashes(htmlspecialchars($_POST['host_main']));
+else
+       $host_main = stripslashes(htmlspecialchars($hosts_default['main']));
+
+// Groupchat host
+if(isset($_POST['host_muc']) && !empty($_POST['host_muc']))
+       $host_muc = stripslashes(htmlspecialchars($_POST['host_muc']));
+else
+       $host_muc = stripslashes(htmlspecialchars($hosts_default['muc']));
+
+// Pubsub host
+if(isset($_POST['host_pubsub']) && !empty($_POST['host_pubsub']))
+       $host_pubsub = stripslashes(htmlspecialchars($_POST['host_pubsub']));
+else
+       $host_pubsub = stripslashes(htmlspecialchars($hosts_default['pubsub']));
+
+// Directory host
+if(isset($_POST['host_vjud']) && !empty($_POST['host_vjud']))
+       $host_vjud = stripslashes(htmlspecialchars($_POST['host_vjud']));
+else
+       $host_vjud = stripslashes(htmlspecialchars($hosts_default['vjud']));
+
+// Anonymous host
+if(isset($_POST['host_anonymous']) && !empty($_POST['host_anonymous']))
+       $host_anonymous = stripslashes(htmlspecialchars($_POST['host_anonymous']));
+else
+       $host_anonymous = stripslashes(htmlspecialchars($hosts_default['anonymous']));
+
+// BOSH host
+if(isset($_POST['host_bosh']) && !empty($_POST['host_bosh']))
+       $host_bosh = stripslashes(htmlspecialchars($_POST['host_bosh']));
+else
+       $host_bosh = stripslashes(htmlspecialchars($hosts_default['bosh']));
+
+// Main BOSH host
+if(isset($_POST['host_bosh_main']) && !empty($_POST['host_bosh_main']))
+       $host_bosh_main = stripslashes(htmlspecialchars($_POST['host_bosh_main']));
+else
+       $host_bosh_main = stripslashes(htmlspecialchars($hosts_default['bosh_main']));
+
+// Mini BOSH host
+if(isset($_POST['host_bosh_mini']) && !empty($_POST['host_bosh_mini']))
+       $host_bosh_mini = stripslashes(htmlspecialchars($_POST['host_bosh_mini']));
+else
+       $host_bosh_mini = stripslashes(htmlspecialchars($hosts_default['bosh_mini']));
+
+// Static host
+if(isset($_POST['host_static']) && !empty($_POST['host_static']))
+       $host_static = stripslashes(htmlspecialchars($_POST['host_static']));
+else
+       $host_static = stripslashes(htmlspecialchars($hosts_default['static']));
+
+// Upload host
+if(isset($_POST['host_upload']) && !empty($_POST['host_upload']))
+       $host_upload = stripslashes(htmlspecialchars($_POST['host_upload']));
+else
+       $host_upload = stripslashes(htmlspecialchars($hosts_default['upload']));
+
+// Generate the hosts XML content
+$hosts_xml = 
+       '<main>'.$host_main.'</main>
+       <muc>'.$host_muc.'</muc>
+       <pubsub>'.$host_pubsub.'</pubsub>
+       <vjud>'.$host_vjud.'</vjud>
+       <anonymous>'.$host_anonymous.'</anonymous>
+       <bosh>'.$host_bosh.'</bosh>
+       <bosh_main>'.$host_bosh_main.'</bosh_main>
+       <bosh_mini>'.$host_bosh_mini.'</bosh_mini>
+       <static>'.$host_static.'</static>
+       <upload>'.$host_upload.'</upload>'
+;
+
+// Write the main configuration
+writeXML('conf', 'hosts', $hosts_xml);
diff --git a/jappixmini/jappix/php/post-main.php b/jappixmini/jappix/php/post-main.php
new file mode 100644 (file)
index 0000000..f3060dd
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the main configuration POST handler (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Service name
+if(isset($_POST['service_name']) && !empty($_POST['service_name']))
+       $service_name = stripslashes(htmlspecialchars($_POST['service_name']));
+else
+       $service_name = stripslashes(htmlspecialchars($main_default['name']));
+
+// Service description
+if(isset($_POST['service_desc']) && !empty($_POST['service_desc']))
+       $service_desc = stripslashes(htmlspecialchars($_POST['service_desc']));
+else
+       $service_desc = stripslashes(htmlspecialchars($main_default['desc']));
+
+// Jappix resource
+if(isset($_POST['jappix_resource']) && !empty($_POST['jappix_resource']))
+       $jappix_resource = stripslashes(htmlspecialchars($_POST['jappix_resource']));
+else
+       $jappix_resource = stripslashes(htmlspecialchars($main_default['resource']));
+
+// Lock host
+if(isset($_POST['lock_host']) && !empty($_POST['lock_host']))
+       $lock_host = 'on';
+else
+       $lock_host = 'off';
+
+// Anonymous mode
+if(isset($_POST['anonymous_mode']) && !empty($_POST['anonymous_mode']))
+       $anonymous_mode = 'on';
+else
+       $anonymous_mode = 'off';
+
+// Registration
+if(isset($_POST['registration']) && !empty($_POST['registration']))
+       $registration = 'on';
+else
+       $registration = 'off';
+
+// BOSH proxy
+if(isset($_POST['bosh_proxy']) && !empty($_POST['bosh_proxy']))
+       $bosh_proxy = 'on';
+else
+       $bosh_proxy = 'off';
+
+// Manager link
+if(isset($_POST['manager_link']) && !empty($_POST['manager_link']))
+       $manager_link = 'on';
+else
+       $manager_link = 'off';
+
+// Groupchats to join
+if(isset($_POST['groupchats_join']) && !empty($_POST['groupchats_join']))
+       $groupchats_join = stripslashes(htmlspecialchars(trim($_POST['groupchats_join'])));
+else
+       $groupchats_join = stripslashes(htmlspecialchars($main_default['groupchats_join']));
+
+// Encryption
+if(isset($_POST['encryption']) && !empty($_POST['encryption']))
+       $encryption = 'on';
+else
+       $encryption = 'off';
+
+// HTTPS storage
+if(isset($_POST['https_storage']) && !empty($_POST['https_storage']))
+       $https_storage = 'on';
+else
+       $https_storage = 'off';
+
+// Force HTTPS
+if(isset($_POST['https_force']) && !empty($_POST['https_force']))
+       $https_force = 'on';
+else
+       $https_force = 'off';
+
+// Compression
+if(isset($_POST['compression']) && !empty($_POST['compression']))
+       $compression = 'on';
+else
+       $compression = 'off';
+
+// Multiple resources
+if(isset($_POST['multi_files']) && ($_POST['multi_files'] == 'on'))
+       $multi_files = 'on';
+else
+       $multi_files = 'off';
+
+// Developer mode
+if(isset($_POST['developer']) && ($_POST['developer'] == 'on'))
+       $developer = 'on';
+else
+       $developer = 'off';
+
+// Generate the configuration XML content
+$conf_xml = 
+       '<name>'.$service_name.'</name>
+       <desc>'.$service_desc.'</desc>
+       <resource>'.$jappix_resource.'</resource>
+       <lock>'.$lock_host.'</lock>
+       <anonymous>'.$anonymous_mode.'</anonymous>
+       <registration>'.$registration.'</registration>
+       <bosh_proxy>'.$bosh_proxy.'</bosh_proxy>
+       <manager_link>'.$manager_link.'</manager_link>
+       <groupchats_join>'.$groupchats_join.'</groupchats_join>
+       <encryption>'.$encryption.'</encryption>
+       <https_storage>'.$https_storage.'</https_storage>
+       <https_force>'.$https_force.'</https_force>
+       <compression>'.$compression.'</compression>
+       <multi_files>'.$multi_files.'</multi_files>
+       <developer>'.$developer.'</developer>'
+;
+
+// Write the main configuration
+writeXML('conf', 'main', $conf_xml);
diff --git a/jappixmini/jappix/php/post-store.php b/jappixmini/jappix/php/post-store.php
new file mode 100644 (file)
index 0000000..abaee58
--- /dev/null
@@ -0,0 +1,100 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the store configuration POST handler (manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Music upload?
+if(isset($_POST['upload'])) {
+       // Get the file path
+       $name_music = $_FILES['music_file']['name'];
+       $temp_music = $_FILES['music_file']['tmp_name'];
+       
+       // Any special name submitted?
+       if(isset($_POST['music_title']) && !empty($_POST['music_title'])) {
+               // Add a form var
+               $music_title = $_POST['music_title'];
+               
+               // Get the file extension
+               $ext_music = getFileExt($name_music);
+               
+               // New name
+               $name_music = '';
+               
+               // Add the artist name?
+               if(isset($_POST['music_artist']) && !empty($_POST['music_artist'])) {
+                       // Add a form var
+                       $music_artist = $_POST['music_artist'];
+                       
+                       // Add the current POST var to the global string
+                       $name_music .= $_POST['music_artist'].' - ';
+               }
+               
+               // Add the music title
+               $name_music .= $_POST['music_title'];
+               
+               // Add the album name?
+               if(isset($_POST['music_album']) && !empty($_POST['music_album'])) {
+                       // Add a form var
+                       $music_album = $_POST['music_album'];
+                       
+                       // Add the current POST var to the global string
+                       $name_music .= ' ['.$_POST['music_album'].']';
+               }
+               
+               // Add the extension
+               $name_music .= '.'.$ext_music;
+       }
+       
+       // Music path with new name
+       $path_music = JAPPIX_BASE.'/store/music/'.$name_music;
+       
+       // An error occured?
+       if(!isSafe($name_music) || $_FILES['music_file']['error'] || !move_uploaded_file($temp_music, $path_music)) { ?>
+       
+               <p class="info smallspace fail"><?php _e("The music could not be received, please retry!"); ?></p>
+       
+       <?php }
+       
+       // Bad extension?
+       else if(!preg_match('/^(.+)(\.(og(g|a)|mp3|wav))$/i', $name_music)) {
+               // Remove the image file
+               if(file_exists($path_music))
+                       unlink($path_music);
+       ?>
+       
+               <p class="info smallspace fail"><?php _e("This is not a valid music file, please encode in Ogg Vorbis, MP3 or WAV!"); ?></p>
+       
+       <?php }
+       
+       // The file has been sent
+       else { ?>
+       
+               <p class="info smallspace success"><?php _e("Your music has been added!"); ?></p>
+       
+       <?php
+               // Reset the form vars
+               $music_title = '';
+               $music_artist = '';
+               $music_album = '';
+       }
+}
+
+// File deletion?
+else if(isset($_POST['remove']))
+       removeElements();
+
+?>
diff --git a/jappixmini/jappix/php/post-users.php b/jappixmini/jappix/php/post-users.php
new file mode 100644 (file)
index 0000000..d217ff0
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the user add POST handler (install & manager)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Marker
+$valid_user = true;
+
+// Administrator name
+if(isset($_POST['user_name']) && !empty($_POST['user_name']))
+       $user_name = trim($_POST['user_name']);
+else
+       $valid_user = false;
+
+// Administrator password (first)
+if(isset($_POST['user_password']) && !empty($_POST['user_password']))
+       $user_password = trim($_POST['user_password']);
+else
+       $valid_user = false;
+
+// Administrator password (second)
+if(isset($_POST['user_repassword']) && ($user_password != $_POST['user_repassword']))
+       $valid_user = false;
+
+// Generate the users XML content
+if($valid_user) {
+       // Add our user
+       manageUsers('add', array($user_name => $user_password));
+       
+       // Reset the user name
+       $user_name = '';
+}
+
+?>
diff --git a/jappixmini/jappix/php/read-design.php b/jappixmini/jappix/php/read-design.php
new file mode 100644 (file)
index 0000000..60499a9
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the design configuration reader
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Get the available backgrounds
+$backgrounds = getBackgrounds();
+$backgrounds_number = count($backgrounds);
+
+// Read the background configuration
+$background = readBackground();
+
+// Backgrounds are missing?
+if(!$backgrounds_number && ($background['type'] == 'image'))
+       $background['type'] = 'default';
+
+switch($background['type']) {
+       // Simple notice input
+       case 'image':
+               $background_image = ' checked=""';
+               $background_default = '';
+               
+               break;
+       
+       // Advanced notice input
+       case 'color':
+               $background_color = ' checked=""';
+               $background_default = '';
+               
+               break;
+}
+
+switch($background['image_repeat']) {
+       // No repeat
+       case 'no-repeat':
+               $background_image_repeat_no = ' selected=""';
+               $background_image_repeat_x = '';
+               
+               break;
+               
+       // Repeat
+       case 'repeat':
+               $background_image_repeat_all = ' selected=""';
+               $background_image_repeat_x = '';
+               
+               break;
+       
+       // Y repeat
+       case 'repeat-y':
+               $background_image_repeat_y = ' selected=""';
+               $background_image_repeat_x = '';
+               
+               break;
+}
+
+switch($background['image_horizontal']) {
+       // Left position
+       case 'left':
+               $background_image_horizontal_left = ' selected=""';
+               $background_image_horizontal_center = '';
+               
+               break;
+       
+       // Right position
+       case 'right':
+               $background_image_horizontal_right = ' selected=""';
+               $background_image_horizontal_center = '';
+               
+               break;
+}
+
+switch($background['image_vertical']) {
+       // Left position
+       case 'top':
+               $background_image_vertical_top = ' selected=""';
+               $background_image_vertical_center = '';
+               
+               break;
+       
+       // Right position
+       case 'bottom':
+               $background_image_vertical_bottom = ' selected=""';
+               $background_image_vertical_center = '';
+               
+               break;
+}
+
+if($background['image_adapt'] == 'on')
+       $background_image_adapt = ' checked=""';
+
+// Read the notice configuration
+$notice_conf = readNotice();
+$notice_text = $notice_conf['notice'];
+
+switch($notice_conf['type']) {
+       // Simple notice input
+       case 'simple':
+               $notice_simple = ' checked=""';
+               $notice_none = '';
+               
+               break;
+       
+       // Advanced notice input
+       case 'advanced':
+               $notice_advanced = ' checked=""';
+               $notice_none = '';
+               
+               break;
+}
+
+?>
diff --git a/jappixmini/jappix/php/read-hosts.php b/jappixmini/jappix/php/read-hosts.php
new file mode 100644 (file)
index 0000000..0b406ac
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the hosts configuration reader
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 29/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Get the protocol we use
+if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on'))
+       $protocol = 'https';
+else
+       $protocol = 'http';
+
+// Get the HTTP host
+$http_host = 'jappix.com';
+
+if($_SERVER['HTTP_HOST']) {
+       $http_host_split = str_replace('www.', '', $_SERVER['HTTP_HOST']);
+       $http_host_split = preg_replace('/:[0-9]+$/i', '', $http_host_split);
+       
+       if($http_host_split)
+               $http_host = $http_host_split;
+}
+
+// Define the default hosts configuration values
+$hosts_conf = array(
+               'main'          => $http_host,
+               'muc'           => 'muc.'.$http_host,
+               'pubsub'        => 'pubsub.'.$http_host,
+               'vjud'          => 'vjud.'.$http_host,
+               'anonymous'     => 'anonymous.'.$http_host,
+               'bosh'          => 'http://'.$http_host.':5280/http-bind',
+               'bosh_main'     => '',
+               'bosh_mini'     => '',
+               'static'        => '',
+               'upload'        => ''
+             );
+
+// Define a default values array
+$hosts_default = $hosts_conf;
+
+// Read the hosts configuration file
+$hosts_data = readXML('conf', 'hosts');
+
+// Read the hosts configuration file
+if($hosts_data) {
+       // Initialize the hosts configuration XML data
+       $hosts_xml = new SimpleXMLElement($hosts_data);
+       
+       // Loop the hosts configuration elements
+       foreach($hosts_xml->children() as $hosts_child) {
+               $hosts_value = $hosts_child->getName();
+               
+               // Only push this to the array if it exists
+               if(isset($hosts_conf[$hosts_value]) && $hosts_child)
+                       $hosts_conf[$hosts_value] = str_replace('{PROTOCOL}', $protocol, $hosts_child);
+       }
+}
+
+// Finally, define the hosts configuration globals
+define('HOST_MAIN', $hosts_conf['main']);
+define('HOST_MUC', $hosts_conf['muc']);
+define('HOST_PUBSUB', $hosts_conf['pubsub']);
+define('HOST_VJUD', $hosts_conf['vjud']);
+define('HOST_ANONYMOUS', $hosts_conf['anonymous']);
+define('HOST_BOSH', $hosts_conf['bosh']);
+define('HOST_BOSH_MAIN', $hosts_conf['bosh_main']);
+define('HOST_BOSH_MINI', $hosts_conf['bosh_mini']);
+define('HOST_STATIC', $hosts_conf['static']);
+define('HOST_UPLOAD', $hosts_conf['upload']);
+
+?>
diff --git a/jappixmini/jappix/php/read-main.php b/jappixmini/jappix/php/read-main.php
new file mode 100644 (file)
index 0000000..4acfa00
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the main configuration reader
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define the default main configuration values
+$main_conf = array(
+               'name'                  => 'Jappix',
+               'desc'                  => 'a free social network',
+               'resource'              => 'Jappix',
+               'lock'                  => 'on',
+               'anonymous'             => 'on',
+               'registration'          => 'on',
+               'bosh_proxy'            => 'on',
+               'manager_link'          => 'on',
+               'groupchats_join'       => '',
+               'encryption'            => 'on',
+               'https_storage'         => 'off',
+               'https_force'           => 'off',
+               'compression'           => 'off',
+               'multi_files'           => 'off',
+               'developer'             => 'off'
+            );
+
+// Define a default values array
+$main_default = $main_conf;
+
+// Read the main configuration file
+$main_data = readXML('conf', 'main');
+
+// Read the main configuration file
+if($main_data) {
+       // Initialize the main configuration XML data
+       $main_xml = new SimpleXMLElement($main_data);
+       
+       // Loop the main configuration elements
+       foreach($main_xml->children() as $main_child) {
+               $main_value = $main_child->getName();
+               
+               // Only push this to the array if it exists
+               if(isset($main_conf[$main_value]) && $main_child)
+                       $main_conf[$main_value] = $main_child;
+       }
+}
+
+// Finally, define the main configuration globals
+define('SERVICE_NAME', $main_conf['name']);
+define('SERVICE_DESC', $main_conf['desc']);
+define('JAPPIX_RESOURCE', $main_conf['resource']);
+define('LOCK_HOST', $main_conf['lock']);
+define('ANONYMOUS', $main_conf['anonymous']);
+define('REGISTRATION', $main_conf['registration']);
+define('BOSH_PROXY', $main_conf['bosh_proxy']);
+define('MANAGER_LINK', $main_conf['manager_link']);
+define('GROUPCHATS_JOIN', $main_conf['groupchats_join']);
+define('ENCRYPTION', $main_conf['encryption']);
+define('HTTPS_STORAGE', $main_conf['https_storage']);
+define('HTTPS_FORCE', $main_conf['https_force']);
+define('COMPRESSION', $main_conf['compression']);
+define('MULTI_FILES', $main_conf['multi_files']);
+define('DEVELOPER', $main_conf['developer']);
+
+?>
diff --git a/jappixmini/jappix/php/send.php b/jappixmini/jappix/php/send.php
new file mode 100644 (file)
index 0000000..a24e418
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Out of Band file send script
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 14/01/12
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the needed files
+require_once('./functions.php');
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed for a special node
+if(isStatic())
+       exit;
+
+// Action on an existing file
+if(isset($_GET['id']) && !empty($_GET['id'])) {
+       $file_id = $_GET['id'];
+       $file_path = JAPPIX_BASE.'/store/send/'.$file_id;
+       
+       // Get file name
+       if(isset($_GET['name']) && !empty($_GET['name']))
+               $file_name = $_GET['name'];
+       else
+               $file_name = $file_id;
+       
+       // Hack?
+       if(!isSafe($file_id)) {
+               header('Status: 406 Not Acceptable', true, 406);
+               exit('HTTP/1.1 406 Not Acceptable');
+       }
+       
+       // File does not exist
+       if(!file_exists($file_path)) {
+               header('Status: 404 Not Found', true, 404);
+               exit('HTTP/1.1 404 Not Found');
+       }
+       
+       // Remove a file
+       if(isset($_GET['action']) && ($_GET['action'] == 'remove')) {
+               header('Status: 204 No Content', true, 204);
+               unlink($file_path);
+       }
+       
+       // Receive a file
+       header("Content-disposition: attachment; filename=\"$file_name\"");
+       header("Content-Type: application/force-download");
+       header("Content-Length: ".filesize($file_path));
+       header("Pragma: no-cache");
+       header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
+       header("Expires: 0");
+       readfile($file_path);
+       unlink($file_path);
+}
+
+// Send a file
+else if((isset($_FILES['file']) && !empty($_FILES['file'])) && (isset($_POST['id']) && !empty($_POST['id'])) && (isset($_POST['location']) && !empty($_POST['location']))) {
+       header('Content-Type: text/xml; charset=utf-8');
+       
+       // Get the file name
+       $tmp_filename = $_FILES['file']['tmp_name'];
+       $filename = $_FILES['file']['name'];
+       
+       // Get the location
+       if(HOST_UPLOAD)
+               $location = HOST_UPLOAD;
+       else
+               $location = $_POST['location'];
+       
+       // Get the file new name
+       $ext = getFileExt($filename);
+       $new_name = preg_replace('/(^)(.+)(\.)(.+)($)/i', '$2', $filename);
+       
+       // Define some vars
+       $name = sha1(time().$filename);
+       $path = JAPPIX_BASE.'/store/send/'.$name.'.'.$ext;
+       
+       // Forbidden file?
+       if(!isSafe($filename) || !isSafe($name.'.'.$ext)) {
+               exit(
+'<jappix xmlns=\'jappix:file:send\'>
+       <error>forbidden-type</error>
+       <id>'.htmlspecialchars($_POST['id']).'</id>
+</jappix>'
+               );
+       }
+       
+       // File upload error?
+       if(!is_uploaded_file($tmp_filename) || !move_uploaded_file($tmp_filename, $path)) {
+               exit(
+'<jappix xmlns=\'jappix:file:send\'>
+       <error>move-error</error>
+       <id>'.htmlspecialchars($_POST['id']).'</id>
+</jappix>'
+               );
+       }
+       
+       // Return the path to the file
+       exit(
+'<jappix xmlns=\'jappix:file:send\'>
+       <url>'.htmlspecialchars($location.'php/send.php?id='.urlencode($name).'.'.urlencode($ext).'&name='.urlencode($filename)).'</url>
+       <desc>'.htmlspecialchars($new_name).'</desc>
+       <id>'.htmlspecialchars($_POST['id']).'</id>
+</jappix>'
+       );
+}
+
+// Error?
+else {
+       header('Status: 400 Bad Request', true, 400);
+       exit('HTTP/1.1 400 Bad Request');
+}
+
+?>
diff --git a/jappixmini/jappix/php/static.php b/jappixmini/jappix/php/static.php
new file mode 100644 (file)
index 0000000..857a6a0
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Static PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <title><?php echo htmlspecialchars(SERVICE_NAME); ?> &bull; <?php _e("Static content server"); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+</head>
+
+<body>
+       <h1><?php echo htmlspecialchars(SERVICE_NAME); ?> - <?php _e("Static content server"); ?></h1>
+       <p><?php printf(T_("This is the static content server for %1s, “%2s”."), htmlspecialchars(SERVICE_NAME), htmlspecialchars(SERVICE_DESC)); ?></p>
+       <?php if(showManagerLink()) { ?>
+       <p><a href="./?m=manager<?php echo keepGet('m', false); ?>"><?php _e("Manager"); ?></a></p>
+       <?php } ?>
+</body>
+
+</html>
+
+<!-- Jappix Static <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/stats-svg.php b/jappixmini/jappix/php/stats-svg.php
new file mode 100644 (file)
index 0000000..e5c2b62
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+The SVG loader for Jappix statistics
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', '..');
+
+// Get the functions
+require_once('./functions.php');
+require_once('./functions-manager.php');
+
+// Get the configuration
+require_once('./read-main.php');
+require_once('./read-hosts.php');
+
+// Get the libs
+require_once('./drawsvgchart.php');
+require_once('./gettext.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Start the session
+session_start();
+
+// Check if the user is authorized
+$is_admin = false;
+
+if((isset($_SESSION['jappix_user']) && !empty($_SESSION['jappix_user'])) && (isset($_SESSION['jappix_password']) && !empty($_SESSION['jappix_password']))) {
+       // Get the session values
+       $user = $_SESSION['jappix_user'];
+       $password = $_SESSION['jappix_password'];
+       
+       // Checks the user is admin
+       $is_admin = isAdmin($user, $password);
+}
+
+// Not admin? Stop the script!
+if(!$is_admin)
+       exit;
+
+// Get the graph type
+if((isset($_GET['g']) && !empty($_GET['g'])))
+       $graph = $_GET['g'];
+else
+       $graph = 'others';
+
+// Get the locale
+if((isset($_GET['l']) && !empty($_GET['l'])))
+       $locale = $_GET['l'];
+else
+       $locale = 'en';
+
+// Include the translations
+includeTranslation($locale, 'main');
+
+$drawsvgchart = new DrawSVGChart;
+
+// Generation vars
+$link = FALSE;
+$evolution = FALSE;
+
+// Access graph?
+if($graph == 'access') {
+       // Values
+       $elements = getMonthlyVisits();
+       $legend = array(array('#5276A9', T_("Visits")));
+       $evolution = TRUE;
+}
+
+// Share graph?
+else if($graph == 'share') {
+       // Values
+       $elements = largestShare(shareStats(), 8);
+       $legend = array(array('#5276A9', T_("Size")));
+}
+
+// Others graph?
+else if($graph == 'others') {
+       // Values
+       $elements = otherStats();
+       $legend = array(array('#5276A9', T_("Size")));
+}
+
+// Generate the chart
+$svgchart = $drawsvgchart->createChart($elements, $legend, $link, $evolution, $graph);
+
+// No error?
+if(!$drawsvgchart->has_errors()) {
+       header('Content-Type: image/svg+xml; charset=utf-8');
+       echo $drawsvgchart->getXMLOutput();
+}
+
+?>
diff --git a/jappixmini/jappix/php/store-tree.php b/jappixmini/jappix/php/store-tree.php
new file mode 100644 (file)
index 0000000..2ccc74c
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This script (re)generates the store sub-folders (after an update)
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Array of the sub-folders to create
+$store_folders = array(
+       'access',
+       'avatars',
+       'backgrounds',
+       'cache',
+       'conf',
+       'logos',
+       'logs',
+       'music',
+       'send',
+       'share',
+       'updates'
+);
+
+// Creates the sub-folders
+for($i = 0; $i < count($store_folders); $i++) {
+       $current = JAPPIX_BASE.'/store/'.$store_folders[$i];
+       
+       // Create the folder itself
+       if(!is_dir($current))
+               mkdir($current, 0777, true);
+       
+       chmod($current, 0777);
+       
+       // Create the security file inside the folder
+       $security_html = securityHTML();
+       
+       file_put_contents($current.'/index.html', $security_html);
+}
+
+?>
diff --git a/jappixmini/jappix/php/upload.php b/jappixmini/jappix/php/upload.php
new file mode 100644 (file)
index 0000000..f28c684
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is the Jappix Static PHP/HTML code
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+?>
+<!DOCTYPE html>
+<?php htmlTag($locale); ?>
+
+<head>
+       <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+       <title><?php echo htmlspecialchars(SERVICE_NAME); ?> &bull; <?php _e("User uploads server"); ?></title>
+       <link rel="shortcut icon" href="./favicon.ico" />
+</head>
+
+<body>
+       <h1><?php echo htmlspecialchars(SERVICE_NAME); ?> - <?php _e("User uploads server"); ?></h1>
+       <p><?php printf(T_("This is the user uploads server for %1s, “%2s”."), htmlspecialchars(SERVICE_NAME), htmlspecialchars(SERVICE_DESC)); ?></p>
+       <?php if(showManagerLink()) { ?>
+       <p><a href="./?m=manager<?php echo keepGet('m', false); ?>"><?php _e("Manager"); ?></a></p>
+       <?php } ?>
+</body>
+
+</html>
+
+<!-- Jappix Upload <?php echo $version; ?> - An open social platform -->
diff --git a/jappixmini/jappix/php/vars-design.php b/jappixmini/jappix/php/vars-design.php
new file mode 100644 (file)
index 0000000..4f70d8e
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the design configuration variables
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 25/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define initial logo form values
+$logo_default = ' checked=""';
+$logo_own = '';
+
+// Define initial background form values
+$background_default = ' checked=""';
+$background_image = '';
+$background_color = '';
+$background_image_repeat_no = '';
+$background_image_repeat_all = '';
+$background_image_repeat_x = ' selected=""';
+$background_image_repeat_y = '';
+$background_image_horizontal_center = ' selected=""';
+$background_image_horizontal_left = '';
+$background_image_horizontal_right = '';
+$background_image_vertical_center = ' selected=""';
+$background_image_vertical_top = '';
+$background_image_vertical_bottom = '';
+$background_image_adapt = '';
+
+// Define initial notice form values
+$notice_none = ' checked=""';
+$notice_simple = '';
+$notice_advanced = '';
+$notice_text = '';
+
+// Current background folder
+$backgrounds_folder = 'backgrounds';
+
+?>
diff --git a/jappixmini/jappix/php/vars-hosts.php b/jappixmini/jappix/php/vars-hosts.php
new file mode 100644 (file)
index 0000000..3d09fcd
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the hosts configuration variables
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 27/05/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define the vars with the hosts configuration constants
+$host_main = htmlspecialchars(HOST_MAIN);
+$host_muc = htmlspecialchars(HOST_MUC);
+$host_pubsub = htmlspecialchars(HOST_PUBSUB);
+$host_vjud = htmlspecialchars(HOST_VJUD);
+$host_anonymous = htmlspecialchars(HOST_ANONYMOUS);
+$host_bosh = htmlspecialchars(HOST_BOSH);
+$host_bosh_main = htmlspecialchars(HOST_BOSH_MAIN);
+$host_bosh_mini = htmlspecialchars(HOST_BOSH_MINI);
+$host_static = htmlspecialchars(HOST_STATIC);
+$host_upload = htmlspecialchars(HOST_UPLOAD);
+
+?>
diff --git a/jappixmini/jappix/php/vars-main.php b/jappixmini/jappix/php/vars-main.php
new file mode 100644 (file)
index 0000000..852eb44
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the main configuration variables
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 26/08/11
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define the vars with the main configuration constants
+$service_name = htmlspecialchars(SERVICE_NAME);
+$service_desc = htmlspecialchars(SERVICE_DESC);
+$jappix_resource = htmlspecialchars(JAPPIX_RESOURCE);
+$lock_host = htmlspecialchars(LOCK_HOST);
+$anonymous_mode = htmlspecialchars(ANONYMOUS);
+$registration = htmlspecialchars(REGISTRATION);
+$bosh_proxy = htmlspecialchars(BOSH_PROXY);
+$manager_link = htmlspecialchars(MANAGER_LINK);
+$groupchats_join = htmlspecialchars(GROUPCHATS_JOIN);
+$encryption = htmlspecialchars(ENCRYPTION);
+$https_storage = htmlspecialchars(HTTPS_STORAGE);
+$https_force = htmlspecialchars(HTTPS_FORCE);
+$compression = htmlspecialchars(COMPRESSION);
+$multi_files = htmlspecialchars(MULTI_FILES);
+$developer = htmlspecialchars(DEVELOPER);
+
+?>
diff --git a/jappixmini/jappix/php/vars-store.php b/jappixmini/jappix/php/vars-store.php
new file mode 100644 (file)
index 0000000..93c62e9
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+These are the store configuration variables
+
+-------------------------------------------------
+
+License: AGPL
+Author: Vanaryon
+Last revision: 28/12/10
+
+*/
+
+// Someone is trying to hack us?
+if(!defined('JAPPIX_BASE'))
+       exit;
+
+// Define the initial music form values
+$music_title = '';
+$music_artist = '';
+$music_album = '';
+
+// Current store folders
+$share_folder = 'share';
+$music_folder = 'music';
+
+?>
diff --git a/jappixmini/jappix/snd/new-chat.oga b/jappixmini/jappix/snd/new-chat.oga
new file mode 100644 (file)
index 0000000..8211d24
Binary files /dev/null and b/jappixmini/jappix/snd/new-chat.oga differ
diff --git a/jappixmini/jappix/snd/notification.oga b/jappixmini/jappix/snd/notification.oga
new file mode 100644 (file)
index 0000000..f22b80b
Binary files /dev/null and b/jappixmini/jappix/snd/notification.oga differ
diff --git a/jappixmini/jappix/snd/receive-message.oga b/jappixmini/jappix/snd/receive-message.oga
new file mode 100644 (file)
index 0000000..f8d6c72
Binary files /dev/null and b/jappixmini/jappix/snd/receive-message.oga differ
diff --git a/jappixmini/jappix/xml/anonymous.xml b/jappixmini/jappix/xml/anonymous.xml
new file mode 100644 (file)
index 0000000..59677b7
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>anonymous.css</css>
+       <js>anonymous.js</js>
+</jappix>
diff --git a/jappixmini/jappix/xml/desktop.xml b/jappixmini/jappix/xml/desktop.xml
new file mode 100644 (file)
index 0000000..4b83d58
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>main.css~images.css~board.css~jquery.datepicker.css~home.css~others.css~tools.css~buddylist.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~archives.css~welcome.css~me.css~rosterx.css</css>
+       <js>jquery.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~jquery.datepicker.js~base64.js~jsjac.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~error.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpauth.js~options.js~integratebox.js~pep.js~presence.js~roster.js~storage.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~archives.js~welcome.js~me.js~rosterx.js</js>
+</jappix>
diff --git a/jappixmini/jappix/xml/install.xml b/jappixmini/jappix/xml/install.xml
new file mode 100644 (file)
index 0000000..f15e387
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>main.css~install.css~images.css</css>
+       <js></js>
+</jappix>
diff --git a/jappixmini/jappix/xml/manager.xml b/jappixmini/jappix/xml/manager.xml
new file mode 100644 (file)
index 0000000..05bd545
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>main.css~manager.css~images.css</css>
+       <js></js>
+</jappix>
diff --git a/jappixmini/jappix/xml/mini.xml b/jappixmini/jappix/xml/mini.xml
new file mode 100644 (file)
index 0000000..b4e638e
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>mini.css</css>
+       <js>jxhr.js~base64.js~jsjac.js~jquery.timers.js~constants.js~datastore.js~browser-detect.js~common.js~date.js~links.js~mini.js</js>
+</jappix>
diff --git a/jappixmini/jappix/xml/mobile.xml b/jappixmini/jappix/xml/mobile.xml
new file mode 100644 (file)
index 0000000..49ca66d
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<jappix xmlns="jappix:file:get">
+       <css>mobile.css~images.css</css>
+       <js>base64.js~jsjac.js~constants.js~browser-detect.js~links.js~mobile.js</js>
+</jappix>
diff --git a/jappixmini/jappixmini.php b/jappixmini/jappixmini.php
new file mode 100644 (file)
index 0000000..d4b1993
--- /dev/null
@@ -0,0 +1,583 @@
+<?php
+
+/**
+* Name: jappixmini
+* Description: Provides a Facebook-like chat using Jappix Mini
+* Version: 1.0
+* Author: leberwurscht <leberwurscht@hoegners.de>
+*
+*/
+
+//
+// Copyright 2012 "Leberwurscht" <leberwurscht@hoegners.de>
+//
+// This file is dual-licensed under the MIT license (see MIT.txt) and the AGPL license (see jappix/COPYING).
+//
+
+/*
+
+Problem:
+* jabber password should not be stored on server
+* jabber password should not be sent between server and browser as soon as the user is logged in
+* jabber password should not be reconstructible from communication between server and browser as soon as the user is logged in
+
+Solution:
+Only store an encrypted version of the jabber password on the server. The encryption key is only available to the browser
+and not to the server (at least as soon as the user is logged in). It can be stored using the jappix setDB function.
+
+This encryption key could be the friendica password, but then this password would be stored in the browser in cleartext.
+It is better to use a hash of the password.
+The server should not be able to reconstruct the password, so we can't take the same hash the server stores. But we can
+ use hash("some_prefix"+password). This will however not work with OpenID logins, for this type of login the password must
+be queried manually.
+
+Problem:
+How to discover the jabber addresses of the friendica contacts?
+
+Solution:
+Each Friendica site with this addon provides a /jappixmini/ module page. We go through our contacts and retrieve
+this information every week using a cron hook.
+
+Problem:
+We do not want to make the jabber address public.
+
+Solution:
+When two friendica users connect using DFRN, the relation gets a DFRN ID and a keypair is generated.
+Using this keypair, we can provide the jabber address only to contacts:
+
+Alice:
+  signed_address = openssl_*_encrypt(alice_jabber_address)
+send signed_address to Bob, who does
+  trusted_address = openssl_*_decrypt(signed_address)
+  save trusted_address
+  encrypted_address = openssl_*_encrypt(bob_jabber_address)
+reply with encrypted_address to Alice, who does
+  decrypted_address = openssl_*_decrypt(encrypted_address)
+  save decrypted_address
+
+Interface for this:
+GET /jappixmini/?role=%s&signed_address=%s&dfrn_id=%s
+
+Response:
+json({"status":"ok", "encrypted_address":"%s"})
+
+*/
+
+function jappixmini_install() {
+register_hook('plugin_settings', 'addon/jappixmini/jappixmini.php', 'jappixmini_settings');
+register_hook('plugin_settings_post', 'addon/jappixmini/jappixmini.php', 'jappixmini_settings_post');
+
+register_hook('page_end', 'addon/jappixmini/jappixmini.php', 'jappixmini_script');
+register_hook('authenticate', 'addon/jappixmini/jappixmini.php', 'jappixmini_login');
+
+register_hook('cron', 'addon/jappixmini/jappixmini.php', 'jappixmini_cron');
+
+// Jappix source download as required by AGPL
+register_hook('about_hook', 'addon/jappixmini/jappixmini.php', 'jappixmini_download_source');
+
+// set standard configuration
+$info_text = get_config("jappixmini", "infotext");
+if (!$info_text) set_config("jappixmini", "infotext",
+       "To get the chat working, you need to know a BOSH host which works with your Jabber account. ".
+       "An example of a BOSH server that works for all accounts is https://bind.jappix.com/, but keep ".
+       "in mind that the BOSH server can read along all chat messages. If you know that your Jabber ".
+       "server also provides an own BOSH server, it is much better to use this one!"
+);
+
+$bosh_proxy = get_config("jappixmini", "bosh_proxy");
+if ($bosh_proxy==="") set_config("jappixmini", "bosh_proxy", "1");
+
+// set addon version so that safe updates are possible later
+$addon_version = get_config("jappixmini", "version");
+if ($addon_version==="") set_config("jappixmini", "version", "1");
+}
+
+
+function jappixmini_uninstall() {
+unregister_hook('plugin_settings', 'addon/jappixmini/jappixmini.php', 'jappixmini_settings');
+unregister_hook('plugin_settings_post', 'addon/jappixmini/jappixmini.php', 'jappixmini_settings_post');
+
+unregister_hook('page_end', 'addon/jappixmini/jappixmini.php', 'jappixmini_script');
+unregister_hook('authenticate', 'addon/jappixmini/jappixmini.php', 'jappixmini_login');
+
+unregister_hook('cron', 'addon/jappixmini/jappixmini.php', 'jappixmini_cron');
+
+unregister_hook('about_hook', 'addon/jappixmini/jappixmini.php', 'jappixmini_download_source');
+}
+
+function jappixmini_plugin_admin(&$a, &$o) {
+       // display instructions and warnings on addon settings page for admin
+
+       if (!file_exists("addon/jappixmini.tgz")) {
+               $o .= '<p><strong style="color:#fff;background-color:#f00">The source archive jappixmini.tgz does not exist. This is probably a violation of the Jappix License (AGPL).</strong></p>';
+       }
+
+       // warn if cron job has not yet been executed
+       $cron_run = get_config("jappixmini", "last_cron_execution");
+       if (!$cron_run) $o .= "<p><strong>Warning: The cron job has not yet been executed. If this message is still there after some time (usually 10 minutes), this means that autosubscribe and autoaccept will not work.</strong></p>";
+
+       // bosh proxy
+       $bosh_proxy = intval(get_config("jappixmini", "bosh_proxy"));
+       $bosh_proxy = intval($bosh_proxy) ? ' checked="checked"' : '';
+       $o .= '<label for="jappixmini-proxy">Activate BOSH proxy</label>';
+       $o .= ' <input id="jappixmini-proxy" type="checkbox" name="jappixmini-proxy" value="1"'.$bosh_proxy.' /><br />';
+
+       // info text field
+       $info_text = get_config("jappixmini", "infotext");
+       $o .= '<p><label for="jappixmini-infotext">Info text to help users with configuration (important if you want to provide your own BOSH host!):</label><br />';
+       $o .= '<textarea id="jappixmini-infotext" name="jappixmini-infotext" rows="5" cols="50">'.htmlentities($info_text).'</textarea></p>';
+
+       // submit button
+       $o .= '<input type="submit" name="jappixmini-admin-settings" value="OK" />';
+}
+
+function jappixmini_plugin_admin_post(&$a) {
+       // set info text
+       $submit = $_REQUEST['jappixmini-admin-settings'];
+       if ($submit) {
+               $info_text = $_REQUEST['jappixmini-infotext'];
+               $bosh_proxy = intval($_REQUEST['jappixmini-proxy']);
+               set_config("jappixmini", "infotext", $info_text);
+               set_config("jappixmini", "bosh_proxy", $bosh_proxy);
+       }
+}
+
+function jappixmini_module() {}
+function jappixmini_init(&$a) {
+       // module page where other Friendica sites can submit Jabber addresses to and also can query Jabber addresses
+        // of local users
+
+       $dfrn_id = $_REQUEST["dfrn_id"];
+       if (!$dfrn_id) killme();
+
+       $role = $_REQUEST["role"];
+       if ($role=="pub") {
+               $r = q("SELECT * FROM `contact` WHERE LENGTH(`pubkey`) AND `dfrn-id`='%s' LIMIT 1",
+                       dbesc($dfrn_id)
+               );
+               if (!count($r)) killme();
+
+               $encrypt_func = openssl_public_encrypt;
+               $decrypt_func = openssl_public_decrypt;
+               $key = $r[0]["pubkey"];
+       } else if ($role=="prv") {
+               $r = q("SELECT * FROM `contact` WHERE LENGTH(`prvkey`) AND `issued-id`='%s' LIMIT 1",
+                       dbesc($dfrn_id)
+               );
+               if (!count($r)) killme();
+
+               $encrypt_func = openssl_private_encrypt;
+               $decrypt_func = openssl_private_decrypt;
+               $key = $r[0]["prvkey"];
+       } else {
+               killme();
+       }
+
+       $uid = $r[0]["uid"];
+
+       // save the Jabber address we received
+       try {
+               $signed_address_hex = $_REQUEST["signed_address"];
+               $signed_address = hex2bin($signed_address_hex);
+
+               $trusted_address = "";
+               $decrypt_func($signed_address, $trusted_address, $key);
+
+               $now = intval(time());
+               set_pconfig($uid, "jappixmini", "id:$dfrn_id", "$now:$trusted_address");
+       } catch (Exception $e) {
+       }
+
+       // do not return an address if user deactivated plugin
+       $activated = get_pconfig($uid, 'jappixmini', 'activate');
+       if (!$activated) killme();
+
+       // return the requested Jabber address
+       try {
+               $username = get_pconfig($uid, 'jappixmini', 'username');
+               $server = get_pconfig($uid, 'jappixmini', 'server');
+               $address = "$username@$server";
+
+               $encrypted_address = "";
+               $encrypt_func($address, $encrypted_address, $key);
+
+               $encrypted_address_hex = bin2hex($encrypted_address);
+
+               $answer = Array(
+                       "status"=>"ok",
+                       "encrypted_address"=>$encrypted_address_hex
+               );
+
+               $answer_json = json_encode($answer);
+               echo $answer_json;
+               killme();
+       } catch (Exception $e) {
+               killme();
+       }
+}
+
+function jappixmini_settings(&$a, &$s) {
+    // addon settings for a user
+
+    $activate = get_pconfig(local_user(),'jappixmini','activate');
+    $activate = intval($activate) ? ' checked="checked"' : '';
+
+    $username = get_pconfig(local_user(),'jappixmini','username');
+    $username = htmlentities($username);
+    $server = get_pconfig(local_user(),'jappixmini','server');
+    $server = htmlentities($server);
+    $bosh = get_pconfig(local_user(),'jappixmini','bosh');
+    $bosh = htmlentities($bosh);
+    $password = get_pconfig(local_user(),'jappixmini','password');
+    $autosubscribe = get_pconfig(local_user(),'jappixmini','autosubscribe');
+    $autosubscribe = intval($autosubscribe) ? ' checked="checked"' : '';
+    $autoapprove = get_pconfig(local_user(),'jappixmini','autoapprove');
+    $autoapprove = intval($autoapprove) ? ' checked="checked"' : '';
+    $encrypt = intval(get_pconfig(local_user(),'jappixmini','encrypt'));
+    $encrypt_checked = $encrypt ? ' checked="checked"' : '';
+    $encrypt_disabled = $encrypt ? '' : ' disabled="disabled"';
+
+    $info_text = get_config("jappixmini", "infotext");
+    $info_text = htmlentities($info_text);
+    $info_text = str_replace("\n", "<br />", $info_text);
+
+    // count contacts
+    $r = q("SELECT COUNT(1) as `cnt` FROM `pconfig` WHERE `uid`=%d AND `cat`='jappixmini' AND `k` LIKE 'id:%%'", local_user());
+    if (count($r)) $contact_cnt = $r[0]["cnt"];
+    else $contact_cnt = 0;
+
+    // count jabber addresses
+    $r = q("SELECT COUNT(1) as `cnt` FROM `pconfig` WHERE `uid`=%d AND `cat`='jappixmini' AND `k` LIKE 'id:%%' AND `v` LIKE '%%@%%'", local_user());
+    if (count($r)) $address_cnt = $r[0]["cnt"];
+    else $address_cnt = 0;
+
+    if (!$activate) {
+       // load scripts if not yet activated so that password can be saved
+        $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/jappix/php/get.php?t=js&amp;g=mini.xml"></script>'."\r\n";
+        $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/jappix/php/get.php?t=js&amp;f=presence.js~caps.js~name.js~roster.js"></script>'."\r\n";
+
+        $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/lib.js"></script>'."\r\n";
+    }
+
+    $s .= '<div class="settings-block">';
+
+    $s .= '<h3>Jappix Mini addon settings</h3>';
+    $s .= '<div>';
+    $s .= '<label for="jappixmini-activate">Activate addon</label>';
+    $s .= ' <input id="jappixmini-activate" type="checkbox" name="jappixmini-activate" value="1"'.$activate.' />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-username">Jabber username</label>';
+    $s .= ' <input id="jappixmini-username" type="text" name="jappixmini-username" value="'.$username.'" />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-server">Jabber server</label>';
+    $s .= ' <input id="jappixmini-server" type="text" name="jappixmini-server" value="'.$server.'" />';
+    $s .= '<br />';
+
+    $s .= '<label for="jappixmini-bosh">Jabber BOSH host</label>';
+    $s .= ' <input id="jappixmini-bosh" type="text" name="jappixmini-bosh" value="'.$bosh.'" />';
+    $s .= '<br />';
+
+    $s .= '<label for="jappixmini-password">Jabber password</label>';
+    $s .= ' <input type="hidden" id="jappixmini-password" name="jappixmini-encrypted-password" value="'.$password.'" />';
+    $s .= ' <input id="jappixmini-clear-password" type="password" value="" onchange="jappixmini_set_password();" />';
+    $s .= '<br />';
+    $onchange = "document.getElementById('jappixmini-friendica-password').disabled = !this.checked;jappixmini_set_password();";
+    $s .= '<label for="jappixmini-encrypt">Encrypt Jabber password with Friendica password (recommended)</label>';
+    $s .= ' <input id="jappixmini-encrypt" type="checkbox" name="jappixmini-encrypt" onchange="'.$onchange.'" value="1"'.$encrypt_checked.' />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-friendica-password">Friendica password</label>';
+    $s .= ' <input id="jappixmini-friendica-password" name="jappixmini-friendica-password" type="password" onchange="jappixmini_set_password();" value=""'.$encrypt_disabled.' />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-autoapprove">Approve subscription requests from Friendica contacts automatically</label>';
+    $s .= ' <input id="jappixmini-autoapprove" type="checkbox" name="jappixmini-autoapprove" value="1"'.$autoapprove.' />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-autosubscribe">Subscribe to Friendica contacts automatically</label>';
+    $s .= ' <input id="jappixmini-autosubscribe" type="checkbox" name="jappixmini-autosubscribe" value="1"'.$autosubscribe.' />';
+    $s .= '<br />';
+    $s .= '<label for="jappixmini-purge">Purge internal list of jabber addresses of contacts</label>';
+    $s .= ' <input id="jappixmini-purge" type="checkbox" name="jappixmini-purge" value="1" />';
+    $s .= '<br />';
+    if ($info_text) $s .= '<br />Configuration help:<p style="margin-left:2em;">'.$info_text.'</p>';
+    $s .= '<br />Status:<p style="margin-left:2em;">Addon knows '.$address_cnt.' Jabber addresses of '.$contact_cnt.' Friendica contacts (takes some time, usually 10 minutes, to update).</p>';
+    $s .= '<input type="submit" name="jappixmini-submit" value="' . t('Submit') . '" />';
+    $s .= ' <input type="button" value="Add contact" onclick="jappixmini_addon_subscribe();" />';
+    $s .= '</div>';
+
+    $s .= '</div>';
+
+    $a->page['htmlhead'] .= "<script type=\"text/javascript\">
+        function jappixmini_set_password() {
+            encrypt = document.getElementById('jappixmini-encrypt').checked;
+            password = document.getElementById('jappixmini-password');
+            clear_password = document.getElementById('jappixmini-clear-password');
+            if (encrypt) {
+                friendica_password = document.getElementById('jappixmini-friendica-password');
+
+                if (friendica_password) {
+                    jappixmini_addon_set_client_secret(friendica_password.value);
+                    jappixmini_addon_encrypt_password(clear_password.value, function(encrypted_password){
+                        password.value = encrypted_password;
+                    });
+                }
+            }
+            else {
+                password.value = clear_password.value;
+            }
+        }
+
+        jQuery(document).ready(function() {
+            encrypt = document.getElementById('jappixmini-encrypt').checked;
+            password = document.getElementById('jappixmini-password');
+            clear_password = document.getElementById('jappixmini-clear-password');
+            if (encrypt) {
+                jappixmini_addon_decrypt_password(password.value, function(decrypted_password){
+                    clear_password.value = decrypted_password;
+                });
+            }
+            else {
+                clear_password.value = password.value;
+            }
+        });
+    </script>";
+}
+
+function jappixmini_settings_post(&$a,&$b) {
+       // save addon settings for a user
+
+       if(! local_user()) return;
+       $uid = local_user();
+
+       if($_POST['jappixmini-submit']) {
+               $encrypt = intval($b['jappixmini-encrypt']);
+               if ($encrypt) {
+                       // check that Jabber password was encrypted with correct Friendica password
+                       $friendica_password = trim($b['jappixmini-friendica-password']);
+                       $encrypted = hash('whirlpool',$friendica_password);
+                       $r = q("SELECT * FROM `user` WHERE `uid`=$uid AND `password`='%s'",
+                               dbesc($encrypted)
+                       );
+                       if (!count($r)) {
+                               info("Wrong friendica password!");
+                               return;
+                       }
+               }
+
+               $purge = intval($b['jappixmini-purge']);
+
+               $username = trim($b['jappixmini-username']);
+               $old_username = get_pconfig($uid,'jappixmini','username');
+               if ($username!=$old_username) $purge = 1;
+
+               $server = trim($b['jappixmini-server']);
+               $old_server = get_pconfig($uid,'jappixmini','server');
+               if ($server!=$old_server) $purge = 1;
+
+               set_pconfig($uid,'jappixmini','username',$username);
+               set_pconfig($uid,'jappixmini','server',$server);
+               set_pconfig($uid,'jappixmini','bosh',trim($b['jappixmini-bosh']));
+               set_pconfig($uid,'jappixmini','password',trim($b['jappixmini-encrypted-password']));
+               set_pconfig($uid,'jappixmini','autosubscribe',intval($b['jappixmini-autosubscribe']));
+               set_pconfig($uid,'jappixmini','autoapprove',intval($b['jappixmini-autoapprove']));
+               set_pconfig($uid,'jappixmini','activate',intval($b['jappixmini-activate']));
+               set_pconfig($uid,'jappixmini','encrypt',$encrypt);
+               info( 'Jappix Mini settings saved.' );
+
+               if ($purge) {
+                       q("DELETE FROM `pconfig` WHERE `uid`=$uid AND `cat`='jappixmini' AND `k` LIKE 'id:%%'");
+                       info( 'List of addresses purged.' );
+               }
+       }
+}
+
+function jappixmini_script(&$a,&$s) {
+    // adds the script to the page header which starts Jappix Mini
+
+    if(! local_user()) return;
+
+    $activate = get_pconfig(local_user(),'jappixmini','activate');
+    if (!$activate) return;
+
+    $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/jappix/php/get.php?t=js&amp;g=mini.xml"></script>'."\r\n";
+    $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/jappix/php/get.php?t=js&amp;f=presence.js~caps.js~name.js~roster.js"></script>'."\r\n";
+
+    $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/lib.js"></script>'."\r\n";
+
+    $username = get_pconfig(local_user(),'jappixmini','username');
+    $username = str_replace("'", "\\'", $username);
+    $server = get_pconfig(local_user(),'jappixmini','server');
+    $server = str_replace("'", "\\'", $server);
+    $bosh = get_pconfig(local_user(),'jappixmini','bosh');
+    $bosh = str_replace("'", "\\'", $bosh);
+    $encrypt = get_pconfig(local_user(),'jappixmini','encrypt');
+    $encrypt = intval($encrypt);
+    $password = get_pconfig(local_user(),'jappixmini','password');
+    $password = str_replace("'", "\\'", $password);
+
+    $autoapprove = get_pconfig(local_user(),'jappixmini','autoapprove');
+    $autoapprove = intval($autoapprove);
+    $autosubscribe = get_pconfig(local_user(),'jappixmini','autosubscribe');
+    $autosubscribe = intval($autosubscribe);
+
+    // set proxy if necessary
+    $use_proxy = get_config('jappixmini','bosh_proxy');
+    if ($use_proxy) {
+        $proxy = $a->get_baseurl().'/addon/jappixmini/proxy.php';
+    }
+    else {
+        $proxy = "";
+    }
+
+    // get a list of jabber accounts of the contacts
+    $contacts = Array();
+    $uid = local_user();
+    $rows = q("SELECT * FROM `pconfig` WHERE `uid`=$uid AND `cat`='jappixmini' AND `k` LIKE 'id:%%'");
+    foreach ($rows as $row) {
+        $key = $row['k'];
+       $pos = strpos($key, ":");
+       $dfrn_id = substr($key, $pos+1);
+        $r = q("SELECT `name` FROM `contact` WHERE `uid`=$uid AND `dfrn-id`='%s' OR `issued-id`='%s'",
+               dbesc($dfrn_id),
+               dbesc($dfrn_id)
+       );
+       $name = $r[0]["name"];
+
+        $value = $row['v'];
+        $pos = strpos($value, ":");
+        $address = substr($value, $pos+1);
+       if (!$address) continue;
+       if (!$name) $name = $address;
+
+       $contacts[$address] = $name;
+    }
+    $contacts_json = json_encode($contacts);
+    $contacts_hash = sha1($contacts_json);
+
+    // get nickname
+    $r = q("SELECT `username` FROM `user` WHERE `uid`=$uid");
+    $nickname = json_encode($r[0]["username"]);
+
+    // add javascript to start Jappix Mini
+    $a->page['htmlhead'] .= "<script type=\"text/javascript\">
+        jQuery(document).ready(function() {
+           jappixmini_addon_start('$server', '$username', '$proxy', '$bosh', $encrypt, '$password', $nickname, $contacts_json, '$contacts_hash', $autoapprove, $autosubscribe);
+        });
+    </script>";
+
+    return;
+}
+
+function jappixmini_login(&$a, &$o) {
+    // create client secret on login to be able to encrypt jabber passwords
+
+    // for setDB and str_sha1, needed by jappixmini_addon_set_client_secret
+    $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/jappix/php/get.php?t=js&amp;f=datastore.js~jsjac.js"></script>'."\r\n";
+
+    // for jappixmini_addon_set_client_secret
+    $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/jappixmini/lib.js"></script>'."\r\n";
+
+    // save hash of password
+    $o = str_replace("<form ", "<form onsubmit=\"jappixmini_addon_set_client_secret(this.elements['id_password'].value);return true;\" ", $o);
+}
+
+function jappixmini_cron(&$a, $d) {
+       // For autosubscribe/autoapprove, we need to maintain a list of jabber addresses of our contacts.
+
+       set_config("jappixmini", "last_cron_execution", $d);
+
+       // go through list of users with jabber enabled
+       $users = q("SELECT `uid` FROM `pconfig` WHERE `cat`='jappixmini' AND (`k`='autosubscribe' OR `k`='autoapprove') AND `v`='1'");
+       logger("jappixmini: Update list of contacts' jabber accounts for ".count($users)." users.");
+
+       foreach ($users as $row) {
+               $uid = $row["uid"];
+
+               // for each user, go through list of contacts
+               $contacts = q("SELECT * FROM `contact` WHERE `uid`=%d AND ((LENGTH(`dfrn-id`) AND LENGTH(`pubkey`)) OR (LENGTH(`issued-id`) AND LENGTH(`prvkey`)))", intval($uid));
+               foreach ($contacts as $contact_row) {
+                       $request = $contact_row["request"];
+                       if (!$request) continue;
+
+                       $dfrn_id = $contact_row["dfrn-id"];
+                       if ($dfrn_id) {
+                               $key = $contact_row["pubkey"];
+                               $encrypt_func = openssl_public_encrypt;
+                               $decrypt_func = openssl_public_decrypt;
+                               $role = "prv";
+                       } else {
+                               $dfrn_id = $contact_row["issued-id"];
+                               $key = $contact_row["prvkey"];
+                               $encrypt_func = openssl_private_encrypt;
+                               $decrypt_func = openssl_private_decrypt;
+                               $role = "pub";
+                       }
+
+                       // check if jabber address already present
+                       $present = get_pconfig($uid, "jappixmini", "id:".$dfrn_id);
+                       $now = intval(time());
+                       if ($present) {
+                               // $present has format "timestamp:jabber_address"
+                               $p = strpos($present, ":");
+                               $timestamp = intval(substr($present, 0, $p));
+
+                               // do not re-retrieve jabber address if last retrieval
+                               // is not older than a week
+                               if ($now-$timestamp<3600*24*7) continue;
+                       }
+
+                       // construct base retrieval address
+                       $pos = strpos($request, "/dfrn_request/");
+                       if ($pos===false) continue;
+
+                       $base = substr($request, 0, $pos)."/jappixmini?role=$role";
+
+                       // construct own address
+                       $username = get_pconfig($uid, 'jappixmini', 'username');
+                       if (!$username) continue;
+                       $server = get_pconfig($uid, 'jappixmini', 'server');
+                       if (!$server) continue;
+
+                       $address = $username."@".$server;
+
+                       // sign address
+                       $signed_address = "";
+                       $encrypt_func($address, $signed_address, $key);
+
+                       // construct request url
+                       $signed_address_hex = bin2hex($signed_address);
+                       $url = $base."&signed_address=$signed_address_hex&dfrn_id=".urlencode($dfrn_id);
+
+                       try {
+                               // send request
+                               $answer_json = fetch_url($url);
+
+                               // parse answer
+                               $answer = json_decode($answer_json);
+                               if ($answer->status != "ok") throw new Exception();
+
+                               $encrypted_address_hex = $answer->encrypted_address;
+                               if (!$encrypted_address_hex) throw new Exception();
+
+                               $encrypted_address = hex2bin($encrypted_address_hex);
+                               if (!$encrypted_address) throw new Exception();
+
+                               // decrypt address
+                               $decrypted_address = "";
+                               $decrypt_func($encrypted_address, $decrypted_address, $key);
+                               if (!$decrypted_address) throw new Exception();
+                       } catch (Exception $e) {
+                               $decrypted_address = "";
+                       }
+
+                       // save address
+                       set_pconfig($uid, "jappixmini", "id:$dfrn_id", "$now:$decrypted_address");
+               }
+       }
+}
+
+function jappixmini_download_source(&$a,&$b) {
+       // Jappix Mini source download link on About page
+
+       $b .= '<h1>Jappix Mini</h1>';
+       $b .= '<p>This site uses the jappixmini addon, which includes Jappix Mini by the <a href="'.$a->get_baseurl().'/addon/jappixmini/jappix/AUTHORS">Jappix authors</a> and is distributed under the terms of the <a href="'.$a->get_baseurl().'/addon/jappixmini/jappix/COPYING">GNU Affero General Public License</a>.</p>';
+       $b .= '<p>You can download the <a href="'.$a->get_baseurl().'/addon/jappixmini.tgz">source code of the addon</a>. The rest of Friendica is distributed under compatible licenses and can be retrieved from <a href="https://github.com/friendica/friendica">https://github.com/friendica/friendica</a> and <a href="https://github.com/friendica/friendica-addons">https://github.com/friendica/friendica-addons</a></p>';
+}
diff --git a/jappixmini/lib.js b/jappixmini/lib.js
new file mode 100644 (file)
index 0000000..a777a7f
--- /dev/null
@@ -0,0 +1,280 @@
+//
+// Copyright 2012 "Leberwurscht" <leberwurscht@hoegners.de>
+//
+// This file is dual-licensed under the MIT license (see MIT.txt) and the AGPL license (see jappix/COPYING).
+//
+
+function jappixmini_addon_xor(str1, str2) {
+    if (str1.length != str2.length) throw "not same length";
+
+    var encoded = "";
+
+    for (var i=0; i<str1.length;i++) {
+        var a = str1.charCodeAt(i);
+        var b = str2.charCodeAt(i);
+        var c = a ^ b;
+
+        encoded += String.fromCharCode(c);
+    }
+
+    return encoded;
+}
+
+function jappixmini_addon_set_client_secret(password) {
+       if (!password) return;
+
+       var salt1 = "h8doCRekWto0njyQohKpdx6BN0UTyC6N";
+       var salt2 = "jdX8OwFC1kWAq3s9uOyAcE8g3UNNO5t3";
+
+       var client_secret1 = str_sha1(salt1+password);
+       var client_secret2 = str_sha1(salt2+password);
+       var client_secret = client_secret1 + client_secret2;
+
+       setPersistent('jappix-mini', 'client-secret', client_secret);
+       console.log("client secret set");
+}
+
+function jappixmini_addon_get_client_secret(callback) {
+       var client_secret = getPersistent('jappix-mini', 'client-secret');
+       if (client_secret===null) {
+               var div = document.getElementById("#jappixmini-password-query-div");
+
+               if (!div) {
+                       div = $('<div id="jappixmini-password-query-div" style="position:fixed;padding:1em;background-color:#F00;color:#fff;top:50px;left:50px;">Retype your Friendica password for chatting:<br></div>');
+
+                       var input = $('<input type="password" id="jappixmini-password-query-input">')
+                       div.append(input);
+
+                       var button = $('<input type="button" value="OK" id="jappixmini-password-query-button">');
+                       div.append(button);
+
+                       $("body").append(div);
+               }
+
+               button.click(function(){
+                       var password = $("#jappixmini-password-query-input").val();
+                       jappixmini_addon_set_client_secret(password);
+                       div.remove();
+
+                       var client_secret = getPersistent('jappix-mini', 'client-secret');
+                       callback(client_secret);
+               });
+       }
+       else {
+               callback(client_secret);
+       }
+}
+
+function jappixmini_addon_encrypt_password(password, callback) {
+       jappixmini_addon_get_client_secret(function(client_secret){
+               // add \0 to password until it has the same length as secret
+               if (password.length>client_secret.length-1) throw "password too long";
+               while (password.length<client_secret.length) {
+                       password += "\0";
+               }
+
+               // xor password with secret
+               var encrypted_password = jappixmini_addon_xor(client_secret, password);
+
+               encrypted_password = encodeURI(encrypted_password)
+               callback(encrypted_password);
+       });
+}
+
+function jappixmini_addon_decrypt_password(encrypted_password, callback) {
+       encrypted_password = decodeURI(encrypted_password);
+
+       jappixmini_addon_get_client_secret(function(client_secret){
+               // xor password with secret
+               var password = jappixmini_addon_xor(client_secret, encrypted_password);
+
+               // remove \0
+               var first_null = password.indexOf("\0")
+               if (first_null==-1) throw "Decrypted password does not contain \\0";
+               password = password.substr(0, first_null);
+
+               callback(password);
+       });
+}
+
+function jappixmini_manage_roster(contacts, contacts_hash, autoapprove, autosubscribe) {
+       // listen for subscriptions
+       con.registerHandler('presence',function(presence){
+               var type = presence.getType();
+               if (type != "subscribe") return;
+
+               var from = fullXID(getStanzaFrom(presence));
+               var xid = bareXID(from);
+               var pstatus = presence.getStatus();
+
+               var approve;
+
+               if (autoapprove && contacts[xid]!==undefined) {
+                       // approve known address
+                       approve = true;
+                       console.log("Approve known Friendica contact "+xid+".");
+               }
+               else if (autoapprove && pstatus && pstatus.indexOf("Friendica")!=-1) {
+                       // Unknown address claims to be a Friendica contact.
+                       // This is probably because the other side knows our
+                       // address, but we do not know the other side yet.
+                       // But it's only a matter of time, so wait - do not
+                       // approve yet and do not annoy the user by asking.
+                       approve = false;
+                       console.log("Do not approve unknown Friendica contact "+xid+" - wait instead.");
+               }
+               else {
+                       // In all other cases, ask the user.
+                       var message = "Accept "+xid+" for chat?";
+                       if (pstatus) message += "\n\nStatus:\n"+pstatus;
+                       approve = confirm(message);
+
+                       // do not ask any more
+                       if (!approve) sendSubscribe(xid, "unsubscribed");
+               }
+
+               if (approve) {
+                       var name = contacts[xid];
+                       if (!name) name = xid;
+
+                       acceptSubscribe(xid, name);
+                       console.log("Accepted "+xid+" ("+name+") for chat.");
+               }
+       });
+
+       // autosubscribe
+       if (!autosubscribe) return;
+
+       var stored_hash = getPersistent("jappix-mini", "contacts-hash");
+       var contacts_changed = (stored_hash != contacts_hash); // stored_hash gets updated later if everything was successful
+       if (!contacts_changed) return;
+
+       console.log("Start autosubscribe.");
+
+       var get_roster = new JSJaCIQ();
+       get_roster.setType('get');
+       get_roster.setQuery(NS_ROSTER);
+
+       con.send(get_roster, function(iq){
+               var handleXML = iq.getQuery();
+
+               // filter out contacts that are already in the roster
+               $(handleXML).find('item').each(function() {
+                        var node = $(this);
+                       var xid = node.attr("jid");
+                       var name = node.attr("name");
+                       var subscription = node.attr("subscription");
+
+                       // ignore accounts that are not in the list
+                       if (contacts[xid]===undefined) return;
+
+                       // add to Friendica group or change name if necessary
+                       var groups = [];
+                       var group_missing = false;
+                       node.find('group').each(function() {
+                               var group_text = $(this).text();
+                               if (group_text) groups.push(group_text);
+                       });
+                       if ($.inArray("Friendica", groups)==-1) {
+                               group_missing = true;
+                               groups.push("Friendica");
+                       }
+
+                       if (group_missing || name!=contacts[xid]) {
+                               sendRoster(xid, null, contacts[xid], groups);
+                               console.log("Added "+xid+" to Friendica group and set name to "+contacts[xid]+".");
+                       }
+
+                       // authorize if necessary
+                       if (subscription=="to") {
+                               sendSubscribe(xid, 'subscribed');
+                               console.log("Authorized "+xid+" automatically.");
+                       }
+
+                       // remove from list
+                       delete contacts[xid];
+               });
+
+               // go through remaining contacts
+               for (var xid in contacts) {if(!contacts.hasOwnProperty(xid)) continue;
+                       // subscribe
+                       var presence = new JSJaCPresence();
+                       presence.setTo(xid);
+                       presence.setType("subscribe");
+
+                       // must contain the word "~Friendica" so the other side knows
+                       // how to handle this
+                       presence.setStatus("I'm "+MINI_NICKNAME+" from ~Friendica.\n[machine-generated message]");
+
+                       con.send(presence);
+                       console.log("Subscribed to "+xid+" automatically.");
+
+                       // add to roster
+                       var iq = new JSJaCIQ();
+                       iq.setType('set');
+                       var iqQuery = iq.setQuery(NS_ROSTER);
+                       var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid}));
+                       item.setAttribute('name', contacts[xid]);
+                       item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, "Friendica"));
+                       con.send(iq);
+                       console.log("Added "+xid+" ("+contacts[xid]+") to roster.");
+               }
+
+               setPersistent("jappix-mini", "contacts-hash", contacts_hash);
+               console.log("Autosubscribe done.");
+       });
+
+}
+
+function jappixmini_addon_subscribe() {
+        if (!window.con) {
+               alert("Not connected.");
+               return;
+        }
+
+       var xid = prompt("Jabber address");
+       sendSubscribe(xid, "subscribe");
+}
+
+function jappixmini_addon_start(server, username, proxy, bosh, encrypted, password, nickname, contacts, contacts_hash, autoapprove, autosubscribe) {
+    var handler = function(password){
+        // check if settings have changed, reinitialize jappix mini if this is the case
+        var settings_identifier = str_sha1(server);
+        settings_identifier += str_sha1(username);
+        settings_identifier += str_sha1(proxy);
+        settings_identifier += str_sha1(bosh);
+        settings_identifier += str_sha1(password);
+        settings_identifier += str_sha1(nickname);
+
+        var saved_identifier = getDB("jappix-mini", "settings-identifier");
+        if (saved_identifier != settings_identifier) {
+            disconnectMini();
+            removeDB('jappix-mini', 'dom');
+            removePersistent("jappix-mini", "contacts-hash");
+        }
+        setDB("jappix-mini", "settings-identifier", settings_identifier);
+
+        // set HOST_BOSH
+        if (proxy)
+            HOST_BOSH = proxy+"?host_bosh="+encodeURI(bosh);
+        else
+            HOST_BOSH = bosh;
+
+        // start jappix mini
+        MINI_NICKNAME = nickname;
+        LOCK_HOST = "off";
+        launchMini(true, false, server, username, password);
+
+        // increase priority over other Jabber clients - does not seem to work?
+        var priority = 101;
+        presenceMini(null,null,priority);
+
+        jappixmini_manage_roster(contacts, contacts_hash, autoapprove, autosubscribe)
+    }
+
+    // decrypt password if necessary
+    if (encrypted)
+        jappixmini_addon_decrypt_password(password, handler);
+    else
+        handler(password);
+}
diff --git a/jappixmini/proxy.php b/jappixmini/proxy.php
new file mode 100644 (file)
index 0000000..a9f6db4
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+
+/*
+
+Jappix - An open social platform
+This is a PHP BOSH proxy
+
+-------------------------------------------------
+
+This file is dual-licensed under the MIT license (see MIT.txt) and the AGPL license (see jappix/COPYING).
+Authors: Vanaryon, Leberwurscht
+
+*/
+
+// PHP base
+define('JAPPIX_BASE', './jappix');
+
+// Get the configuration
+require_once('./jappix/php/functions.php');
+require_once('./jappix/php/read-main.php');
+require_once('./jappix/php/read-hosts.php');
+
+// Optimize the page rendering
+hideErrors();
+compressThis();
+
+// Not allowed?
+if(!BOSHProxy()) {
+       header('Status: 403 Forbidden', true, 403);
+       exit('HTTP/1.1 403 Forbidden');
+}
+
+// custom BOSH host
+$HOST_BOSH = HOST_BOSH;
+if(isset($_GET['host_bosh']) && $_GET['host_bosh']) {
+       $host_bosh = $_GET['host_bosh'];
+       if (substr($host_bosh, 0, 7)==="http://" || substr($host_bosh, 0, 8)==="https://") {
+               $HOST_BOSH = $host_bosh;
+       }
+}
+
+// OPTIONS method?
+if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
+       // CORS headers
+       header('Access-Control-Allow-Origin: *');
+       header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
+       header('Access-Control-Allow-Headers: Content-Type');
+       header('Access-Control-Max-Age: 31536000');
+       
+       exit;
+}
+
+// Read POST content
+$data = file_get_contents('php://input');
+
+// POST method?
+if($data) {
+       // CORS headers
+       header('Access-Control-Allow-Origin: *');
+       header('Access-Control-Allow-Headers: Content-Type');
+       
+       $method = 'POST';
+}
+
+// GET method?
+else if(isset($_GET['data']) && $_GET['data'] && isset($_GET['callback']) && $_GET['callback']) {
+       $method = 'GET';
+       $data = $_GET['data'];
+       $callback = $_GET['callback'];
+}
+
+// Invalid method?
+else {
+       header('Status: 400 Bad Request', true, 400);
+       exit('HTTP/1.1 400 Bad Request');
+}
+
+// HTTP headers
+$headers = array('User-Agent: Jappix (BOSH PHP Proxy)', 'Connection: keep-alive', 'Content-Type: text/xml; charset=utf-8', 'Content-Length: '.strlen($data));
+
+// CURL is better if available
+if(function_exists('curl_init'))
+       $use_curl = true;
+else
+       $use_curl = false;
+
+// CURL caused problems for me
+$use_curl = false;
+
+// CURL stream functions
+if($use_curl) {
+       // Initialize CURL
+       $connection = curl_init($HOST_BOSH);
+       
+       // Set the CURL settings
+       curl_setopt($connection, CURLOPT_HEADER, 0);
+       curl_setopt($connection, CURLOPT_POST, 1);
+       curl_setopt($connection, CURLOPT_POSTFIELDS, $data);
+       curl_setopt($connection, CURLOPT_FOLLOWLOCATION, true);
+       curl_setopt($connection, CURLOPT_HTTPHEADER, $headers);
+       curl_setopt($connection, CURLOPT_VERBOSE, 0);
+       curl_setopt($connection, CURLOPT_CONNECTTIMEOUT, 30);
+       curl_setopt($connection, CURLOPT_TIMEOUT, 30);
+       curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 0);
+       curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 0);
+       curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1);
+       
+       // Get the CURL output
+       $output = curl_exec($connection);
+}
+
+// Built-in stream functions
+else {
+       // HTTP parameters
+       $parameters = array('http' => array(
+                                       'method' => 'POST',
+                                       'content' => $data
+                                     )
+                     );
+
+       $parameters['http']['header'] = $headers;
+
+       // Change default timeout
+       ini_set('default_socket_timeout', 30);
+
+       // Create the connection
+       $stream = @stream_context_create($parameters);
+       $connection = @fopen($HOST_BOSH, 'rb', false, $stream);
+
+       // Failed to connect!
+       if($connection == false) {
+               header('Status: 502 Proxy Error', true, 502);
+               exit('HTTP/1.1 502 Proxy Error');
+       }
+
+       // Allow stream blocking to handle incoming BOSH data
+       @stream_set_blocking($connection, true);
+
+       // Get the output content
+       $output = @stream_get_contents($connection);
+}
+
+// Cache headers
+header('Cache-Control: no-cache, must-revalidate');
+header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+
+// POST output
+if($method == 'POST') {
+       // XML header
+       header('Content-Type: text/xml; charset=utf-8');
+       
+       if(!$output)
+               echo('<body xmlns=\'http://jabber.org/protocol/httpbind\' type=\'terminate\'/>');
+       else
+               echo($output);
+}
+
+// GET output
+if($method == 'GET') {
+       // JSON header
+       header('Content-type: application/json');
+       
+       // Encode output to JSON
+       $json_output = json_encode($output);
+       
+       if(($output == false) || ($output == '') || ($json_output == 'null'))
+               echo($callback.'({"reply":"<body xmlns=\'http:\/\/jabber.org\/protocol\/httpbind\' type=\'terminate\'\/>"});');
+       else
+               echo($callback.'({"reply":'.$json_output.'});');
+}
+
+// Close the connection
+if($use_curl)
+       curl_close($connection);
+else
+       @fclose($connection);
+
+?>
diff --git a/mathjax.tgz b/mathjax.tgz
new file mode 100644 (file)
index 0000000..bb591e1
Binary files /dev/null and b/mathjax.tgz differ
diff --git a/mathjax/README b/mathjax/README
new file mode 100644 (file)
index 0000000..023e1c8
--- /dev/null
@@ -0,0 +1,31 @@
+Addon for Friendika to include MathJax (LaTeX math syntax)
+
+This addon lets your users use LaTeX to type mathematical formulas
+within their posts. MathJax takes care about the best method for the
+browser to display the formula and provides compatibility to 99%
+of the modern browsers.
+
+You can either use the MathJax CDN online, thus loading the required javascript
+libraries from the MathJax cloud, or use a local installation of MathJax.
+Please see the plugin settings in the admin panel for configuration possibles.
+If you don't set up a local MathJax instance, leave the configuration untouched
+it will fall back to the MathJax cloud as default value.
+
+If you don't use the admin panel add mathjax to the list of active addons
+
+$a->config['system']['addon'] = [..., mathjax, ...]
+
+To select the source of the included javascript libraries add a line
+
+$a->config['mathjax']['baseurl'] = 'the URL to your MathJax installation';
+
+to your .htconfig.php file. If this line is not there, the addon assumes that
+you want to use the MathJax cloud (CDN).
+
+Please note that your usage of the CDN is governed by the "MathJax CDN Terms of
+Service" see http://www.mathjax.org/download/mathjax-cdn-terms-of-service/
+
+Author:  Tobias Diekershoff
+         http://diekershoff.homeunix.net/friendika/profile/tobias
+         email: tobias.diekershoff@gmx.net
+
diff --git a/mathjax/admin.tpl b/mathjax/admin.tpl
new file mode 100644 (file)
index 0000000..1c723cd
--- /dev/null
@@ -0,0 +1,2 @@
+{{ inc field_input.tpl with $field=$baseurl }}{{endinc }}
+<div class="submit"><input type="submit" name="page_site" value="$submit" /></div>
diff --git a/mathjax/mathjax.php b/mathjax/mathjax.php
new file mode 100644 (file)
index 0000000..7105772
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * Name: MathJax
+ * Description: Addon for Friendika to include MathJax (LaTeX math syntax)
+ * Version: 1.0
+ * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
+ * License: 3-clause BSD license
+ */
+
+function mathjax_install() {
+    register_hook('page_header', 'addon/mathjax/mathjax.php', 'mathjax_page_header');
+    register_hook('plugin_settings', 'addon/mathjax/mathjax.php', 'mathjax_settings'); 
+    register_hook('plugin_settings_post', 'addon/mathjax/mathjax.php', 'mathjax_settings_post');
+    logger('installed js_math plugin');
+}
+function mathjax_uninstall() {
+    unregister_hook('page_header', 'addon/mathjax/mathjax.php', 'mathjax_page_header');
+    unregister_hook('plugin_settings', 'addon/mathjax/mathjax.php', 'mathjax_settings'); 
+    unregister_hook('plugin_settings_post', 'addon/mathjax/mathjax.php', 'mathjax_settings_post');
+}
+function mathjax_settings_post ($a, $post) {
+    if (! local_user())
+        return;
+    // don't check statusnet settings if statusnet submit button is not clicked
+    if (!x($_POST,'mathjax-submit'))
+        return;
+    set_pconfig(local_user(),'mathjax','use',intval($_POST['mathjax_use']));
+}
+function mathjax_settings (&$a, &$s) {
+    if (! local_user())
+        return;
+    $use = get_pconfig(local_user(),'mathjax','use');
+    $usetext = (($use) ? ' checked="checked" ' : '');
+    $s .= '<div class="settings-block">';
+    $s .= '<h3>MathJax '.t('Settings').'</h3>';
+    $s .= '<p>'.t('The MathJax addon renders mathematical formulae written using the LaTeX syntax surrounded by the usual $$ or an eqnarray block in the postings of your wall,network tab and private mail.').'</p>';
+    $s .= '<label id="mathjax_label" for="mathjax_use">'.t('Use the MathJax renderer').'</label>';
+    $s .= '<input id="mathjax_use" type="checkbox" name="mathjax_use" value="1"'. $usetext .' />';
+    $s .= '<div class="clear"></div>';
+
+    $s .= '<div class="settings-submit-wrapper" ><input type="submit" id="mathjax-submit" name="mathjax-submit" class="settings-submit" value="' . t('Submit') . '" /></div>';
+    $s .= '</div>';
+}
+/*  we need to add one JavaScript include command to the html output
+ *  note that you have to check the jsmath/easy/load.js too.
+ */
+function mathjax_page_header($a, &$b) {
+    //  if the visitor of the page is not a local_user, use MathJax
+    //  otherwise check the users settings.
+    $url = get_config ('mathjax','baseurl');
+       if(! $url)
+               $url = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
+    if (! local_user()) {
+        $b .= '<script type="text/javascript" src="'.$url.'"></script>';
+    } else {
+        $use = get_pconfig(local_user(),'mathjax','use');
+        if ($use) { 
+            $b .= '<script type="text/javascript" src="'.$url.'"></script>';
+        }
+    }
+}
+function mathjax_plugin_admin_post (&$a) {
+    $baseurl = ((x($_POST, 'baseurl')) ? trim($_POST['baseurl']) : 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML');
+    set_config('mathjax','baseurl',$baseurl);
+    info( t('Settings updated.'). EOL);
+}
+function mathjax_plugin_admin (&$a, &$o) {
+       $t = file_get_contents( dirname(__file__)."/admin.tpl");
+        if (get_config('mathjax','baseurl','') == '') {
+            set_config('mathjax','baseurl','http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML');
+        }
+        $o = replace_macros( $t, array(
+               '$baseurl' => array('baseurl', t('MathJax Base URL'), get_config('mathjax','baseurl' ), t('The URL for the javascript file that should be included to use MathJax. Can be either the MathJax CDN or another installation of MathJax.')),
+            ));
+}
index 6897cb89077e099b1266efead83947f5f48971be..c484aa03f77b7275c44b3b9185c3fe05735b888c 100755 (executable)
Binary files a/nsfw.tgz and b/nsfw.tgz differ
index 0f94158bc83b19dd2d4b92623d808d9bf2be72fc..4a65b72089994063e8cde0c67ef3edb34faf8759 100755 (executable)
@@ -94,7 +94,8 @@ function nsfw_prepare_body(&$a,&$b) {
        $found = false;
        if(count($arr)) {
                foreach($arr as $word) {
-                       if(! strlen(trim($word))) {
+                       $word = trim($word);
+                       if(! strlen($word)) {
                                continue;
                        }
                        if(strpos($word,'/') === 0) {
index 84fb7b81480dc2f78f829613d5046bdf223f5f92..c94f01b214e1c3285c36513420649539f2517c4f 100644 (file)
Binary files a/page.tgz and b/page.tgz differ
index 72972eded43064a970d1db2962e9cac3ab64aa01..129af41249f05a5a4cb03fc8d580524dfcec9f29 100755 (executable)
@@ -24,7 +24,8 @@ function page_getpage($uid) {
        $pagelist = array();
 
        $contacts = q("SELECT `id`, `url`, `name`, `micro`FROM `contact`
-                       WHERE `network`= 'dfrn' AND `forum` = 1 AND `uid` = %d",
+                       WHERE `network`= 'dfrn' AND `forum` = 1 AND `uid` = %d
+                       order by name asc ",
                        intval($uid)
        );
 
@@ -47,14 +48,28 @@ function page_page_end($a,&$b) {
                        <h3>'.t("Forums").'</h3></div>
                        <div id="sidebar-page-list"><ul>';
 
+
        $contacts = page_getpage($a->user['uid']);
 
+       $total_shown = 0;
+       $more = false;
+
        foreach($contacts as $contact) {
                $page .= '<li style="list-style-type: none;" class="tool"><img height="20" width="20" src="' . $contact['micro'] .'" alt="' . $contact['url'] . '" /> <a href="'.$a->get_baseurl().'/redir/'.$contact["id"].'" title="' . $contact['url'] . '" class="label" target="external-link">'.
                                $contact["name"]."</a></li>";
+               $total_shown ++;
+               if($total_shown == 6) {
+                       $more = true;
+                       $page .= '</ul><div id="hide-comments-page-widget" class="fakelink" onclick="showHideComments(\'page-widget\');" >' . t('show more') 
+                               . '</div><div id="collapsed-comments-page-widget" style="display: none;" ><ul>';
+               } 
        }
+       if($more)
+               $page .= '</div>';
        $page .= "</ul></div></div>";
        if (sizeof($contacts) > 0)
                $a->page['aside'] = $page . $a->page['aside'];
 }
-?>
+
+
+
diff --git a/pages.tgz b/pages.tgz
deleted file mode 100644 (file)
index 5fd23f7..0000000
Binary files a/pages.tgz and /dev/null differ
index 886435132b2414a41fad54fcda6f9e9d39a3480a..f808058756047a4330a6e55ce5e7bef4c9db2c54 100755 (executable)
Binary files a/posterous.tgz and b/posterous.tgz differ
index eda2a93a4582a7b142dea6b08dca62a83efae71e..25a009c5145f25b303654e7173deb063db741694 100755 (executable)
@@ -153,6 +153,9 @@ function posterous_post_local(&$a,&$b) {
 
 function posterous_send(&$a,&$b) {
 
+       logger('posterous_send: invoked');
+       return;
+
     if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
         return;
 
diff --git a/privacy_image_cache/README.md b/privacy_image_cache/README.md
new file mode 100644 (file)
index 0000000..63970d3
--- /dev/null
@@ -0,0 +1,4 @@
+Once activated, this addon acs as a proxy between the user and external image resources.
+If external images are to be shown, like avatars or embedded images, the server retrieves the image and the local link is sent to the user.
+By using this proxy, the server hosting the original image cannot retrieve personal information of the user like the IP address, User Agent or Cookies.
+However, the remote server will be able to track the IP address of the server hosting the friendica installation.
\ No newline at end of file
diff --git a/privacy_image_cache/privacy_image_cache.php b/privacy_image_cache/privacy_image_cache.php
new file mode 100644 (file)
index 0000000..45aeb08
--- /dev/null
@@ -0,0 +1,175 @@
+<?php
+
+/**
+ * Name: Privacy Image Cache
+ * Version: 0.1
+ * Author: Tobias Hößl <https://github.com/CatoTH/>
+ */
+
+define("PRIVACY_IMAGE_CACHE_DEFAULT_TIME", 86400); // 1 Day
+
+require_once('include/security.php');
+
+function privacy_image_cache_install() {
+    register_hook('bbcode',       'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_bbcode_hook');
+    register_hook('display_item', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_display_item_hook');
+    register_hook('ping_xmlize',  'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_ping_xmlize_hook');
+    register_hook('cron',         'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_cron');
+}
+
+
+function privacy_image_cache_uninstall() {
+    unregister_hook('bbcode',       'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_bbcode_hook');
+    unregister_hook('display_item', 'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_display_item_hook');
+    unregister_hook('ping_xmlize',  'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_ping_xmlize_hook');
+    unregister_hook('cron',         'addon/privacy_image_cache/privacy_image_cache.php', 'privacy_image_cache_cron');
+}
+
+
+function privacy_image_cache_module() {}
+
+
+function privacy_image_cache_init() {
+    $urlhash = 'pic:' . sha1($_REQUEST['url']);
+    $r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' LIMIT 1", $urlhash );
+    if (count($r)) {
+        $img_str = $r[0]['data'];
+    }
+    else {
+        require_once("Photo.php");
+
+        $img_str = fetch_url($_REQUEST['url'],true);
+        $img = new Photo($img_str);
+        if($img->is_valid()) {
+            $img->store(0, 0, $urlhash, $_REQUEST['url'], '', 100);
+            $img_str = $img->imageString();
+        }
+    }
+
+
+    header("Content-type: image/jpeg");
+    header("Expires: " . gmdate("D, d M Y H:i:s", time() + (3600*24)) . " GMT");
+    header("Cache-Control: max-age=" . (3600*24));
+
+    echo $img_str;
+
+    killme();
+}
+
+/**
+ * @param $url string
+ * @return boolean
+ */
+function privacy_image_cache_is_local_image($url) {
+    if ($url[0] == '/') return true;
+    $baseurl = get_app()->get_baseurl();
+    return (substr($url, 0, strlen($baseurl)) == $baseurl);
+}
+
+/**
+ * @param array $matches
+ * @return string
+ */
+function privacy_image_cache_img_cb($matches) {
+    if (privacy_image_cache_is_local_image($matches[2])) return $matches[2];
+    return $matches[1] . "/privacy_image_cache/?url=" . escape_tags(addslashes($matches[2])) . $matches[3];
+}
+
+/**
+ * @param App $a
+ * @param string $o
+ */
+function privacy_image_cache_bbcode_hook(&$a, &$o) {
+    $o = preg_replace_callback("/(<img [^>]*src *= *[\"'])([^\"']+)([\"'][^>]*>)/siU", "privacy_image_cache_img_cb", $o);
+}
+
+
+/**
+ * @param App $a
+ * @param string $o
+ */
+function privacy_image_cache_display_item_hook(&$a, &$o) {
+    if (isset($o["output"])) {
+        if (isset($o["output"]["thumb"]) && !privacy_image_cache_is_local_image($o["output"]["thumb"]))
+            $o["output"]["thumb"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["output"]["thumb"]));
+        if (isset($o["output"]["author-avatar"]) && !privacy_image_cache_is_local_image($o["output"]["author-avatar"]))
+            $o["output"]["author-avatar"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["output"]["author-avatar"]));
+    }
+}
+
+
+/**
+ * @param App $a
+ * @param string $o
+ */
+function privacy_image_cache_ping_xmlize_hook(&$a, &$o) {
+    if ($o["photo"] != "" && !privacy_image_cache_is_local_image($o["photo"]))
+        $o["photo"] = "/privacy_image_cache/?url=" . escape_tags(addslashes($o["photo"]));
+}
+
+
+/**
+ * @param App $a
+ * @param null|object $b
+ */
+function privacy_image_cache_cron(&$a, &$b) {
+    $cachetime = get_config('privacy_image_cache','cache_time');
+    if (!$cachetime) $cachetime = PRIVACY_IMAGE_CACHE_DEFAULT_TIME;
+
+    $last = get_config('pi_cache','last_delete');
+    $time = time();
+    if ($time < ($last + 3600)) return;
+
+    logger("Purging old Cache of the Privacy Image Cache", LOGGER_DEBUG);
+    q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%" AND `created` < NOW() - INTERVAL %d SECOND', $cachetime);
+    set_config('pi_cache', 'last_delete', $time);
+}
+
+
+
+
+/**
+ * @param App $a
+ * @param null|object $o
+ */
+function privacy_image_cache_plugin_admin(&$a, &$o){
+
+
+    $o = '<input type="hidden" name="form_security_token" value="' . get_form_security_token("picsave") . '">';
+
+    $cachetime = get_config('privacy_image_cache','cache_time');
+    if (!$cachetime) $cachetime = PRIVACY_IMAGE_CACHE_DEFAULT_TIME;
+    $cachetime_h = Ceil($cachetime / 3600);
+
+    $o .= '<label for="pic_cachetime">' . t('Lifetime of the cache (in hours)') . '</label>
+        <input id="pic_cachetime" name="cachetime" type="text" value="' . escape_tags($cachetime_h) . '"><br style="clear: both;">';
+
+    $o .= '<input type="submit" name="save" value="' . t('Save') . '">';
+
+    $o .= '<h4>' . t('Cache Statistics') . '</h4>';
+
+    $num = q('SELECT COUNT(*) num, SUM(LENGTH(data)) size FROM `photo` WHERE `uid`=0 AND `contact-id`=0 AND `resource-id` LIKE "pic:%%"');
+    $o .= '<label for="statictics_num">' . t('Number of items') . '</label><input style="color: gray;" id="statistics_num" disabled value="' . escape_tags($num[0]['num']) . '"><br style="clear: both;">';
+    $size = Ceil($num[0]['size'] / (1024 * 1024));
+    $o .= '<label for="statictics_size">' . t('Size of the cache') . '</label><input style="color: gray;" id="statistics_size" disabled value="' . $size . ' MB"><br style="clear: both;">';
+
+    $o .= '<input type="submit" name="delete_all" value="' . t('Delete the whole cache') . '">';
+}
+
+
+/**
+ * @param App $a
+ * @param null|object $o
+ */
+function privacy_image_cache_plugin_admin_post(&$a, &$o){
+    check_form_security_token_redirectOnErr('/admin/plugins/privacy_image_cache', 'picsave');
+
+    if (isset($_REQUEST['save'])) {
+        $cachetime_h = IntVal($_REQUEST['cachetime']);
+        if ($cachetime_h < 1) $cachetime_h = 1;
+        set_config('privacy_image_cache','cache_time', $cachetime_h * 3600);
+    }
+    if (isset($_REQUEST['delete_all'])) {
+        q('DELETE FROM `photo` WHERE `uid` = 0 AND `resource-id` LIKE "pic:%%"');
+    }
+}
\ No newline at end of file
index 7ef9d884ffc87d5708dfdc5d4ab5ea1f3981cb4f..790bc064f5f93159b04341834142d5b1d9385850 100644 (file)
Binary files a/smiley_pack.tgz and b/smiley_pack.tgz differ
index 3a0db669460de5e8000b51bada20b71f21a6261d..a612c476589022d971813cdd9829936e147ad9b5 100644 (file)
Binary files a/smiley_pack/icons/animals/cat.gif and b/smiley_pack/icons/animals/cat.gif differ
diff --git a/smiley_pack/icons/tired/yawn.gif b/smiley_pack/icons/tired/yawn.gif
new file mode 100644 (file)
index 0000000..d451480
Binary files /dev/null and b/smiley_pack/icons/tired/yawn.gif differ
index 7f4bfb7b643de06caa53754b10e46cd55efcd4ca..ed4d0e651405e8d56d57f8794779c61f7b8628dd 100644 (file)
@@ -214,8 +214,8 @@ function smiley_pack_smilies(&$a,&$b) {
        $b['texts'][] = ':basketball';
        $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/basketball.gif' . '" alt="' . ':basketball' . '" />';
 
-       $b['texts'][] = ':bowling';
-       $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/bowling.gif' . '" alt="' . ':bowling' . '" />';
+       $b['texts'][] = '~bowling';
+       $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/bowling.gif' . '" alt="' . '~bowling' . '" />';
 
        $b['texts'][] = ':cycling';
        $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/sport/cycling.gif' . '" alt="' . ':cycling' . '" />';
@@ -284,6 +284,9 @@ function smiley_pack_smilies(&$a,&$b) {
        $b['texts'][] = ':pillow';
        $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/tired/pillow.gif' . '" alt="' . ':pillow' . '" />';
 
+       $b['texts'][] = ':yawn';
+       $b['icons'][] = '<img src="' . $a->get_baseurl() . '/addon/smiley_pack/icons/tired/yawn.gif' . '" alt="' . ':yawn' . '" />';
+
 #Fight/Flame/Violent smileys
 
        $b['texts'][] = ':2guns';
index e4e86ba2f85cc0196e96c0954014e888c45c9ab3..13cc144374578f471c55502ad6226830f9ceaad2 100644 (file)
Binary files a/smilies_adult.tgz and b/smilies_adult.tgz differ
index 2b41f5a47aa3324b1eb4b5021aeebb0d560a64a5..33fbc68a9ca9e9f70c864f4b0e82cdc16e803c49 100755 (executable)
Binary files a/statusnet.tgz and b/statusnet.tgz differ
index c4100e88e509b667a16db8274ac75a5905010770..dd8761680f365f99a186b832a8f2fd78af401e1f 100755 (executable)
@@ -2,7 +2,7 @@
 /**
  * Name: StatusNet Connector
  * Description: Relay public postings to a connected StatusNet account
- * Version: 1.0.4
+ * Version: 1.0.5
  * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
  */
  
@@ -342,7 +342,7 @@ function statusnet_settings(&$a,&$s) {
                        $s .= '<label id="statusnet-default-label" for="statusnet-default">'. t('Send public postings to StatusNet by default') .'</label>';
                        $s .= '<input id="statusnet-default" type="checkbox" name="statusnet-default" value="1" ' . $defchecked . '/>';
                        $s .= '<div class="clear"></div>';
-                        $s .= '<label id="statusnet-sendtaglinks-label" for="statusnet-sendtaglinks">'.t('Send #tag links to StatusNet').'</label>';
+                        $s .= '<label id="statusnet-sendtaglinks-label" for="statusnet-sendtaglinks">'.t('Send linked #-tags and @-names to StatusNet').'</label>';
                         $s .= '<input id="statusnet-sendtaglinks" type="checkbox" name="statusnet-sendtaglinks" value="1" '. $linkschecked . '/>';
                        $s .= '</div><div class="clear"></div>';
 
@@ -435,9 +435,9 @@ function statusnet_post_hook(&$a,&$b) {
                 // shorten all the links in a 200000 character long essay.
                 if (! $b['title']=='') {
                     $tmp = $b['title'] . ' : '. $b['body'];
-                    $tmp = substr($tmp, 0, 4*$max_char);
+//                    $tmp = substr($tmp, 0, 4*$max_char);
                 } else {
-                    $tmp = substr($b['body'], 0, 3*$max_char);
+                    $tmp = $b['body']; // substr($b['body'], 0, 3*$max_char);
                 }
                 // if [url=bla][img]blub.png[/img][/url] get blub.png
                 $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp);
@@ -453,7 +453,10 @@ function statusnet_post_hook(&$a,&$b) {
                 // that is, don't send if the option is not set in the 
                 // connector settings
                 if ($linksenabled=='0') {
+                    // #-tags
                     $tmp = preg_replace( '/#\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '#$2', $tmp);
+                    // @-mentions
+                    $tmp = preg_replace( '/@\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '@$2', $tmp);
                 }
                 // preserve links to webpages
                 $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\](\w+.*?)\[\/url\]/i', '$2 $1', $tmp);
@@ -489,9 +492,14 @@ function statusnet_post_hook(&$a,&$b) {
                         $msg = implode(' ', $e);
                        $msg .= '... ' . $shortlink;
                }
-               // and now tweet it :-)
-               if(strlen($msg))
-                       $dent->post('statuses/update', array('status' => $msg));
+               // and now dent it :-)
+               if(strlen($msg)) {
+                    $result = $dent->post('statuses/update', array('status' => $msg));
+                    logger('statusnet_post send, result: ' . print_r($result, true), LOGGER_DEBUG);
+                    if ($result->error) {
+                        logger('Send to StatusNet failed: "' . $result->error . '"');
+                    }
+                }
        }
 }
 
index 52a05cc6600b304661107df14cdf29825de91d5c..e011308e2d7d2cf27332bd5d46abd8e68569e902 100755 (executable)
Binary files a/twitter.tgz and b/twitter.tgz differ
index 12bb6664691b695bee8921e98637404784bb7330..ff08976c79613d98828d078c0b603c1c1f25158b 100755 (executable)
@@ -21,10 +21,13 @@ Online version of this document: http://ur1.ca/35mml
 
 ___ Requirements ___
 
-To use this plugin you have to register your Friendica instance as an
-_client application_ for Twitter with _read and write_ access, we do not intend
-to use Twitter for login. The registration can be done at twitter.com/apps
-and you need to have a Twitter account to do so.
+To use this plugin you have to register an application for your friendica
+instance on Twitter with
+  * read and write access
+  * don't set a callback URL
+  * we do not intend to use Twitter for login
+The registration can be done at twitter.com/apps and you need a Twitter
+account for doing so.
 
 After you registered the application you get an OAuth consumer key / secret
 pair that identifies your app, you will need them for configuration.
index 32b4980f55a2df4ebba7486150a29b1cc9729d5f..0ac9396dff0630db80899f239b42d84c4bd1c7ac 100755 (executable)
@@ -2,7 +2,7 @@
 /**
  * Name: Twitter Connector
  * Description: Relay public postings to a connected Twitter account
- * Version: 1.0.3
+ * Version: 1.0.4
  * Author: Tobias Diekershoff <http://diekershoff.homeunix.net/friendika/profile/tobias>
  */
 
@@ -198,7 +198,7 @@ function twitter_settings(&$a,&$s) {
                         $s .= '<label id="twitter-default-label" for="twitter-default">'. t('Send public postings to Twitter by default') .'</label>';
                         $s .= '<input id="twitter-default" type="checkbox" name="twitter-default" value="1" ' . $defchecked . '/>';
                        $s .= '<div class="clear"></div>';
-                        $s .= '<label id="twitter-sendtaglinks-label" for="twitter-sendtaglinks">'.t('Send #tag links to Twitter').'</label>';
+                        $s .= '<label id="twitter-sendtaglinks-label" for="twitter-sendtaglinks">'.t('Send linked #-tags and @-names to Twitter').'</label>';
                         $s .= '<input id="twitter-sendtaglinks" type="checkbox" name="twitter-sendtaglinks" value="1" '. $linkschecked . '/>';
                        $s .= '</div><div class="clear"></div>';
 
@@ -301,9 +301,9 @@ function twitter_post_hook(&$a,&$b) {
                 // shorten all the links in a 200000 character long essay.
                 if (! $b['title']=='') {
                     $tmp = $b['title'] . ' : '. $b['body'];
-                    $tmp = substr($tmp, 0, 4*$max_char);
+//                    $tmp = substr($tmp, 0, 4*$max_char);
                 } else {
-                    $tmp = substr($b['body'], 0, 3*$max_char);
+                    $tmp = $b['body']; // substr($b['body'], 0, 3*$max_char);
                 }
                 // if [url=bla][img]blub.png[/img][/url] get blub.png
                 $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\]\[img\](\\w+.*?)\\[\\/img\]\\[\\/url\]/i', '$2', $tmp);
@@ -319,7 +319,10 @@ function twitter_post_hook(&$a,&$b) {
                 // that is, don't send if the option is not set in the 
                 // connector settings
                 if ($linksenabled=='0') {
+                    // #-tags
                     $tmp = preg_replace( '/#\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '#$2', $tmp);
+                    // @-mentions
+                    $tmp = preg_replace( '/@\[url\=(\w+.*?)\](\w+.*?)\[\/url\]/i', '@$2', $tmp);
                 }
                 $tmp = preg_replace( '/\[url\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\](\w+.*?)\[\/url\]/i', '$2 $1', $tmp);
                 $tmp = preg_replace( '/\[bookmark\=(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)\](\w+.*?)\[\/bookmark\]/i', '$2 $1', $tmp);
@@ -357,7 +360,10 @@ function twitter_post_hook(&$a,&$b) {
                // and now tweet it :-)
                if(strlen($msg)) {
                        $result = $tweet->post('statuses/update', array('status' => $msg));
-                       logger('twitter_post send' , LOGGER_DEBUG);
+                       logger('twitter_post send, result: ' . print_r($result, true), LOGGER_DEBUG);
+                       if ($result->error) {
+                               logger('Send to Twitter failed: "' . $result->error . '"');
+                       }
                }
        }
 }
index 47d5f588c285e211f26093c1d99cdccb23bdc093..f3b1857838ac7c0594cf2b9c5c6c5a45f5296ec1 100755 (executable)
Binary files a/widgets.tgz and b/widgets.tgz differ
diff --git a/widgets/widget_friendheader.php b/widgets/widget_friendheader.php
new file mode 100644 (file)
index 0000000..20a84e2
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+function friendheader_widget_name() {
+       return "Shows friends as a bar";
+}
+function friendheader_widget_help() {
+       return "";
+}
+
+function friendheader_widget_args(){
+       return Array();
+}
+
+function friendheader_widget_size(){
+       return Array('780px','140px');
+}
+
+
+function friendheader_widget_content(&$a, $conf){
+
+       $r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.* FROM `profile` 
+                       LEFT JOIN `user` ON `profile`.`uid` = `user`.`uid`
+                       WHERE `user`.`uid` = %s AND `profile`.`is-default` = 1 LIMIT 1",
+                       intval($conf['uid'])
+       );
+       if(!count($r)) return;
+       $a->profile = $r[0];
+
+       $o = "";
+       $o .= "<style>
+               body {font-size: 0.8em; margin: 0px; padding: 0px;}
+               #contact-block { overflow: hidden; height: auto; }
+               .contact-block-h4 { float: left; margin: 0px; }
+               .allcontact-link { float: right; margin: 0px; }
+               .contact-block-content { clear:both; }
+               .contact-block-div { display: block !important; float: left!important; width: 50px!important; height: 50px!important; margin: 2px!important;}
+               
+       </style>";
+       $o .= _abs_url(contact_block());
+       $o .= "<a href='".$a->get_baseurl().'/profile/'.$a->profile['nickname']."' target=new>". t('Get added to this list!') ."</a>";
+       
+       return $o;
+}
index b07bf6e0d9ac6965afcc92cf5dfaa0204063937d..dce99d58df5097f1ca829e42caf5b3123260a889 100755 (executable)
Binary files a/wppost.tgz and b/wppost.tgz differ
index de876958272899c9d05ed7df031c595ce1b582d4..4ecd81aa3d3847377fcecd38290cadaf99174633 100755 (executable)
@@ -1,11 +1,13 @@
 
-#wppost-enable-label, #wppost-username-label, #wppost-password-label, #wppost-blog-label, #wppost-bydefault-label {
+#wppost-enable-label, #wppost-username-label, #wppost-password-label, 
+#wppost-blog-label, #wppost-bydefault-label, #wppost-backlink-label {
        float: left;
        width: 200px;
        margin-top: 10px;
 }
 
-#wppost-checkbox, #wppost-username, #wppost-password, #wppost-blog, #wppost-bydefault {
+#wppost-checkbox, #wppost-username, #wppost-password, 
+#wppost-blog, #wppost-bydefault, #wppost-backlink {
        float: left;
        margin-top: 10px;
 }
index 28e4e36946af907978a89f16acf6045e1470f60d..216c6417c171fed939616d7c4e3281c100584b6e 100755 (executable)
@@ -60,8 +60,10 @@ function wppost_settings(&$a,&$s) {
     $checked = (($enabled) ? ' checked="checked" ' : '');
 
     $def_enabled = get_pconfig(local_user(),'wppost','post_by_default');
+    $back_enabled = get_pconfig(local_user(),'wppost','backlink');
 
     $def_checked = (($def_enabled) ? ' checked="checked" ' : '');
+    $back_checked = (($back_enabled) ? ' checked="checked" ' : '');
 
        $wp_username = get_pconfig(local_user(), 'wppost', 'wp_username');
        $wp_password = get_pconfig(local_user(), 'wppost', 'wp_password');
@@ -95,6 +97,11 @@ function wppost_settings(&$a,&$s) {
     $s .= '<div id="wppost-bydefault-wrapper">';
     $s .= '<label id="wppost-bydefault-label" for="wppost-bydefault">' . t('Post to WordPress by default') . '</label>';
     $s .= '<input id="wppost-bydefault" type="checkbox" name="wp_bydefault" value="1" ' . $def_checked . '/>';
+
+    $s .= '<div id="wppost-backlink-wrapper">';
+    $s .= '<label id="wppost-backlink-label" for="wppost-backlink">' . t('Provide a backlink to the Friendica post') . '</label>';
+    $s .= '<input id="wppost-backlink" type="checkbox" name="wp_backlink" value="1" ' . $back_checked . '/>';
+
     $s .= '</div><div class="clear"></div>';
 
     /* provide a submit button */
@@ -113,6 +120,7 @@ function wppost_settings_post(&$a,&$b) {
                set_pconfig(local_user(),'wppost','wp_username',trim($_POST['wp_username']));
                set_pconfig(local_user(),'wppost','wp_password',trim($_POST['wp_password']));
                set_pconfig(local_user(),'wppost','wp_blog',trim($_POST['wp_blog']));
+               set_pconfig(local_user(),'wppost','backlink',trim($_POST['wp_backlink']));
 
        }
 
@@ -189,8 +197,15 @@ function wppost_send(&$a,&$b) {
 
                $title = '<title>' . (($b['title']) ? $b['title'] : t('Post from Friendica')) . '</title>';
                $post = $title . bbcode($b['body']);
+
+               $wp_backlink = intval(get_pconfig($b['uid'],'wppost','backlink'));
+               if($wp_backlink && $b['plink'])
+                       $post .= EOL . EOL . '<a href="' . $b['plink'] . '">' 
+                               . t('Read the original post and comment stream on Friendica') . '</a>' . EOL . EOL;
+
                $post = xmlify($post);
 
+
                $xml = <<< EOT
 <?xml version=\"1.0\" encoding=\"utf-8\"?>
 <methodCall>