aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfriendica <info@friendica.com>2014-01-18 23:49:39 -0800
committerfriendica <info@friendica.com>2014-01-18 23:49:39 -0800
commit724ad4505628d493b43b4f585512d67dc0b4ee76 (patch)
tree4fb920a79e3dff961a6301ec56ec9f40e91f6af3
parent3f7032e542e3c451507fc9266ab3536155c8190f (diff)
downloadvolse-hubzilla-724ad4505628d493b43b4f585512d67dc0b4ee76.tar.gz
volse-hubzilla-724ad4505628d493b43b4f585512d67dc0b4ee76.tar.bz2
volse-hubzilla-724ad4505628d493b43b4f585512d67dc0b4ee76.zip
add ajaxchat library - needs a lot of integration work to handle decentralisation (e.g. chatroom@website) and zotid w/permissions (e.g. ACL controlled chatrooms); we can also rip out a lot of stuff we don't need.
-rw-r--r--library/ajaxchat/chat/changelog.txt846
-rw-r--r--library/ajaxchat/chat/chat.sql47
-rw-r--r--library/ajaxchat/chat/css/Cobalt.css122
-rw-r--r--library/ajaxchat/chat/css/Core.css115
-rw-r--r--library/ajaxchat/chat/css/Lithium.css116
-rw-r--r--library/ajaxchat/chat/css/Mercury.css154
-rw-r--r--library/ajaxchat/chat/css/MyBB.css115
-rw-r--r--library/ajaxchat/chat/css/Oxygen.css116
-rw-r--r--library/ajaxchat/chat/css/Plum.css112
-rw-r--r--library/ajaxchat/chat/css/Sulfur.css116
-rw-r--r--library/ajaxchat/chat/css/Uranium.css178
-rw-r--r--library/ajaxchat/chat/css/beige.css114
-rw-r--r--library/ajaxchat/chat/css/black.css115
-rw-r--r--library/ajaxchat/chat/css/fonts.css100
-rw-r--r--library/ajaxchat/chat/css/global.css278
-rw-r--r--library/ajaxchat/chat/css/grey.css115
-rw-r--r--library/ajaxchat/chat/css/ie5-6.css70
-rw-r--r--library/ajaxchat/chat/css/index.html0
-rw-r--r--library/ajaxchat/chat/css/plum_images/plum.pngbin0 -> 18601 bytes
-rw-r--r--library/ajaxchat/chat/css/plum_images/plum2.pngbin0 -> 9172 bytes
-rw-r--r--library/ajaxchat/chat/css/print.css114
-rw-r--r--library/ajaxchat/chat/css/prosilver.css154
-rw-r--r--library/ajaxchat/chat/css/shoutbox.css168
-rw-r--r--library/ajaxchat/chat/css/subSilver.css117
-rw-r--r--library/ajaxchat/chat/css/subblack2.css117
-rw-r--r--library/ajaxchat/chat/css/vBulletin.css127
-rw-r--r--library/ajaxchat/chat/flash/FABridge.swfbin0 -> 7609 bytes
-rw-r--r--library/ajaxchat/chat/flash/index.html0
-rw-r--r--library/ajaxchat/chat/img/audio.pngbin0 -> 3966 bytes
-rw-r--r--library/ajaxchat/chat/img/autoscroll.pngbin0 -> 4181 bytes
-rw-r--r--library/ajaxchat/chat/img/delete.pngbin0 -> 241 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/angel.pngbin0 -> 959 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/confused.pngbin0 -> 904 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/cool.pngbin0 -> 864 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/crying.pngbin0 -> 899 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/devilish.pngbin0 -> 855 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/eek.pngbin0 -> 826 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/error.pngbin0 -> 653 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/favorite.pngbin0 -> 788 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/glasses.pngbin0 -> 949 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/grin.pngbin0 -> 905 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/help.pngbin0 -> 932 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/idea.pngbin0 -> 863 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/important.pngbin0 -> 717 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/index.html0
-rw-r--r--library/ajaxchat/chat/img/emoticons/kiss.pngbin0 -> 871 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/monkey.pngbin0 -> 830 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/plain.pngbin0 -> 894 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/razz.pngbin0 -> 772 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/sad.pngbin0 -> 891 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/smile-big.pngbin0 -> 856 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/smile.pngbin0 -> 892 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/surprise.pngbin0 -> 894 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/warning.pngbin0 -> 603 bytes
-rw-r--r--library/ajaxchat/chat/img/emoticons/wink.pngbin0 -> 914 bytes
-rw-r--r--library/ajaxchat/chat/img/help.pngbin0 -> 1359 bytes
-rw-r--r--library/ajaxchat/chat/img/index.html0
-rw-r--r--library/ajaxchat/chat/img/license.txt45
-rw-r--r--library/ajaxchat/chat/img/loading-sprite.pngbin0 -> 4995 bytes
-rw-r--r--library/ajaxchat/chat/img/pixel.gifbin0 -> 43 bytes
-rw-r--r--library/ajaxchat/chat/img/playback.pngbin0 -> 961 bytes
-rw-r--r--library/ajaxchat/chat/img/settings.pngbin0 -> 1151 bytes
-rw-r--r--library/ajaxchat/chat/img/users.pngbin0 -> 1277 bytes
-rw-r--r--library/ajaxchat/chat/index.php24
-rw-r--r--library/ajaxchat/chat/install.php80
-rw-r--r--library/ajaxchat/chat/js/FABridge.js591
-rw-r--r--library/ajaxchat/chat/js/chat.js2940
-rw-r--r--library/ajaxchat/chat/js/config.js261
-rw-r--r--library/ajaxchat/chat/js/custom.js16
-rw-r--r--library/ajaxchat/chat/js/index.html0
-rw-r--r--library/ajaxchat/chat/js/lang/ar.js92
-rw-r--r--library/ajaxchat/chat/js/lang/bg.js92
-rw-r--r--library/ajaxchat/chat/js/lang/ca.js91
-rw-r--r--library/ajaxchat/chat/js/lang/cy.js93
-rw-r--r--library/ajaxchat/chat/js/lang/cz.js91
-rw-r--r--library/ajaxchat/chat/js/lang/da.js91
-rw-r--r--library/ajaxchat/chat/js/lang/de.js91
-rw-r--r--library/ajaxchat/chat/js/lang/el.js92
-rw-r--r--library/ajaxchat/chat/js/lang/en.js91
-rw-r--r--library/ajaxchat/chat/js/lang/es.js92
-rw-r--r--library/ajaxchat/chat/js/lang/et.js91
-rw-r--r--library/ajaxchat/chat/js/lang/fi.js93
-rw-r--r--library/ajaxchat/chat/js/lang/fr.js92
-rw-r--r--library/ajaxchat/chat/js/lang/gl.js92
-rw-r--r--library/ajaxchat/chat/js/lang/he.js92
-rw-r--r--library/ajaxchat/chat/js/lang/hr.js91
-rw-r--r--library/ajaxchat/chat/js/lang/hu.js91
-rw-r--r--library/ajaxchat/chat/js/lang/in.js91
-rw-r--r--library/ajaxchat/chat/js/lang/index.html0
-rw-r--r--library/ajaxchat/chat/js/lang/it.js93
-rw-r--r--library/ajaxchat/chat/js/lang/ja.js91
-rw-r--r--library/ajaxchat/chat/js/lang/ka.js91
-rw-r--r--library/ajaxchat/chat/js/lang/kr.js91
-rw-r--r--library/ajaxchat/chat/js/lang/mk.js9
-rw-r--r--library/ajaxchat/chat/js/lang/nl-be.js92
-rw-r--r--library/ajaxchat/chat/js/lang/nl.js92
-rw-r--r--library/ajaxchat/chat/js/lang/no.js92
-rw-r--r--library/ajaxchat/chat/js/lang/pl.js92
-rw-r--r--library/ajaxchat/chat/js/lang/pt-br.js92
-rw-r--r--library/ajaxchat/chat/js/lang/pt-pt.js92
-rw-r--r--library/ajaxchat/chat/js/lang/ro.js92
-rw-r--r--library/ajaxchat/chat/js/lang/ru.js93
-rw-r--r--library/ajaxchat/chat/js/lang/sk.js92
-rw-r--r--library/ajaxchat/chat/js/lang/sl.js92
-rw-r--r--library/ajaxchat/chat/js/lang/sr.js92
-rw-r--r--library/ajaxchat/chat/js/lang/sv.js92
-rw-r--r--library/ajaxchat/chat/js/lang/th.js92
-rw-r--r--library/ajaxchat/chat/js/lang/tr.js92
-rw-r--r--library/ajaxchat/chat/js/lang/uk.js92
-rw-r--r--library/ajaxchat/chat/js/lang/zh-tw.js91
-rw-r--r--library/ajaxchat/chat/js/lang/zh.js92
-rw-r--r--library/ajaxchat/chat/js/logs.js128
-rw-r--r--library/ajaxchat/chat/js/shoutbox.js12
-rw-r--r--library/ajaxchat/chat/lib/.htaccess4
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChat.php3326
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatDataBase.php81
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatEncoding.php138
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatFileSystem.php22
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatHTTPHeader.php56
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatLanguage.php102
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatMySQLDataBase.php92
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatMySQLQuery.php89
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatMySQLiDataBase.php91
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatMySQLiQuery.php81
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatString.php37
-rw-r--r--library/ajaxchat/chat/lib/class/AJAXChatTemplate.php329
-rw-r--r--library/ajaxchat/chat/lib/class/CustomAJAXChat.php124
-rw-r--r--library/ajaxchat/chat/lib/class/CustomAJAXChatInterface.php21
-rw-r--r--library/ajaxchat/chat/lib/class/CustomAJAXChatShoutBox.php25
-rw-r--r--library/ajaxchat/chat/lib/classes.php26
-rw-r--r--library/ajaxchat/chat/lib/config.php.example209
-rw-r--r--library/ajaxchat/chat/lib/custom.php11
-rw-r--r--library/ajaxchat/chat/lib/data/channels.php16
-rw-r--r--library/ajaxchat/chat/lib/data/users.php40
-rw-r--r--library/ajaxchat/chat/lib/lang/ar.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/bg.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/ca.php125
-rw-r--r--library/ajaxchat/chat/lib/lang/cy.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/cz.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/da.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/de.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/el.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/en.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/es.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/et.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/fa.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/fi.php125
-rw-r--r--library/ajaxchat/chat/lib/lang/fr.php125
-rw-r--r--library/ajaxchat/chat/lib/lang/gl.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/he.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/hr.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/hu.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/in.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/it.php125
-rw-r--r--library/ajaxchat/chat/lib/lang/ja.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/ka.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/kr.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/mk.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/nl-be.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/nl.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/no.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/pl.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/pt-br.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/pt-pt.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/ro.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/ru.php125
-rw-r--r--library/ajaxchat/chat/lib/lang/sk.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/sl.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/sr.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/sv.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/th.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/tr.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/uk.php124
-rw-r--r--library/ajaxchat/chat/lib/lang/zh-tw.php123
-rw-r--r--library/ajaxchat/chat/lib/lang/zh.php124
-rw-r--r--library/ajaxchat/chat/lib/template/loggedIn.html387
-rw-r--r--library/ajaxchat/chat/lib/template/loggedOut.html78
-rw-r--r--library/ajaxchat/chat/lib/template/logs.html276
-rw-r--r--library/ajaxchat/chat/lib/template/shoutbox.html60
-rw-r--r--library/ajaxchat/chat/license.txt28
-rw-r--r--library/ajaxchat/chat/readme.html436
-rw-r--r--library/ajaxchat/chat/socket/.htaccess4
-rw-r--r--library/ajaxchat/chat/socket/server71
-rw-r--r--library/ajaxchat/chat/socket/server.conf22
-rw-r--r--library/ajaxchat/chat/socket/server.rb400
-rw-r--r--library/ajaxchat/chat/sounds/index.html0
-rw-r--r--library/ajaxchat/chat/sounds/license.txt28
-rw-r--r--library/ajaxchat/chat/sounds/sound_1.mp3bin0 -> 16462 bytes
-rw-r--r--library/ajaxchat/chat/sounds/sound_2.mp3bin0 -> 19074 bytes
-rw-r--r--library/ajaxchat/chat/sounds/sound_3.mp3bin0 -> 37808 bytes
-rw-r--r--library/ajaxchat/chat/sounds/sound_4.mp3bin0 -> 52168 bytes
-rw-r--r--library/ajaxchat/chat/sounds/sound_5.mp3bin0 -> 32631 bytes
-rw-r--r--library/ajaxchat/chat/sounds/sound_6.mp3bin0 -> 4994 bytes
-rw-r--r--library/ajaxchat/chat/src/EmptySwf.as32
-rw-r--r--library/ajaxchat/chat/src/FABridge.as943
-rw-r--r--library/ajaxchat/chat/src/index.html0
-rw-r--r--library/ajaxchat/readme.md77
197 files changed, 24150 insertions, 0 deletions
diff --git a/library/ajaxchat/chat/changelog.txt b/library/ajaxchat/chat/changelog.txt
new file mode 100644
index 000000000..733eb994c
--- /dev/null
+++ b/library/ajaxchat/chat/changelog.txt
@@ -0,0 +1,846 @@
+Blueimp's AJAX Chat Changelog
+=============================
+
+
+Version 0.1 (06.06.2007):
+-------------------------------
+First release.
+
+
+Version 0.1.0.1 (10.06.2007):
+-------------------------------
+New features:
+- Added dutch localization - thanks to Nic Mertens
+
+
+Version 0.1.0.2 (11.06.2007):
+-------------------------------
+Bugfixes:
+- Smiley replacement of ";)" could produce invalid XHTML - fixed
+
+
+Version 0.1.0.3 (11.06.2007):
+-------------------------------
+New features:
+- Added sample phpBB2 integration
+
+
+Version 0.1.0.4 (12.06.2007):
+-------------------------------
+Bugfixes:
+- Replaced PHP short tags with long version ( <? => <?php ) in template files
+ This makes the Chat work on servers with php.ini setting "short_open_tag = off"
+
+
+Version 0.1.0.5 (23.06.2007):
+-------------------------------
+Bugfixes:
+- Channel names and language variables were not HTML-encoded in template output.
+ This could lead to invalid XHTML, e.g. if a channel name contained the ampersand ("&").
+
+
+Version 0.1.1 (05.07.2007):
+-------------------------------
+New features:
+- Long words are split on client side to avoid horizontal scrolling.
+- New IRC-style command to roll dice: /roll [number]d[sides]
+
+
+Version 0.1.1.1 (12.07.2007):
+-------------------------------
+New features:
+- Added spanish localization - thanks to Manu Quintans
+
+
+Version 0.1.1.2 (01.08.2007):
+-------------------------------
+
+Bugfixes:
+- Added limits (1-100) to the dice number and sides
+
+
+Version 0.1.1.3 (02.08.2007):
+-------------------------------
+Bugfixes:
+- dateTime had been dependent on local server time.
+ dateTime served is now GMT and calculated and formatted on client side through JavaScript
+
+
+Version 0.1.1.4 (14.08.2007):
+-------------------------------
+Bugfixes:
+- Long hyperlinks are now split while preserving the url information
+- Connection problems don't interrupt the chat update anymore
+
+
+Version 0.1.1.5 (14.08.2007):
+-------------------------------
+Bugfixes:
+- Connection timeout error message now only appears if sending messsage data (POST) fails
+
+
+Version 0.2 (16.08.2007):
+-------------------------------
+New features:
+- Integrated login page style with main style
+- Added multiple styles (beige, black, grey)
+- Added style settings to lib/config.php
+- Integrated persistent style switcher
+- Added custom JavaScript file supposed for overwriting client side functionality
+- Added subSilver style for phpBB2 integration
+- Added subsilver2 and prosilver style for phpBB3 integration
+- Updated phpBB integration to set style from phpBB user style setting
+
+Bugfixes:
+- Adjusted paths in default templates to make the chat work if index.php is located on the document root ('/')
+
+Other changes:
+- Moved ajaxChatConfig['url'] from lib/template/loggedIn.php file to js/config.js
+- Moved language settings from index.php to lib/config.php
+- Moved phpBB root path setting from index.php to lib/config.php
+
+
+Version 0.2.0.1 (17.08.2007):
+-------------------------------
+New features:
+- Easier phpBB integration - forum users are now logged in with their userName and userID automatically.
+ It is not required any more to include userID and userName of registered users in the link to the chat.
+
+
+Version 0.2.0.2 (19.08.2007):
+-------------------------------
+Bugfixes:
+- Channel selector did not work with Internet Explorer - fixed.
+- Style switcher did not work with Internet Explorer - fixed.
+
+
+Version 0.2.1 (21.08.2007):
+-------------------------------
+New features:
+- Updated CSS styles - chat messages window now adjusts to the browser window.
+
+Bugfixes:
+- If a registered user lost his session while logged in he could not login again until timeout.
+This is now fixed by removing the registered user from the online list prior to a new login.
+- The login method had been called on every request with a given userName parameter even if logged in - fixed.
+
+Other changes:
+- Rewrote the DataBase code to make it possible to use a given DataBase link identifier.
+
+
+Version 0.2.1.1 (24.08.2007):
+-------------------------------
+Bugfixes:
+- Internet Explorer 6 can't cope with the updated CSS - added a stylesheet for IE 5-6 to fix this.
+
+
+Version 0.2.1.2 (24.08.2007):
+-------------------------------
+Bugfixes:
+- Code and variable name changes in index.php and lib/config.php to avoid naming conflicts with global variables.
+- Fixed phpBB integration for usernames containing the ampersand ("&") which phpBB stores as HTML entity ("&amp;").
+
+
+Version 0.2.1.3 (24.08.2007):
+-------------------------------
+New features:
+- Added the max length variables of userName and messageText to the template output.
+
+Other changes:
+- Changed the database type for the chat messages from TINYTEXT (8 bit - 255 chars) to TEXT (16 bit - 65535 chars).
+
+
+Version 0.2.1.4 (24.08.2007):
+-------------------------------
+Changes:
+- Users don't get kicked for inactivity anymore. Only a closed browser window will produce a timeout.
+
+
+Version 0.2.1.5 (25.08.2007):
+-------------------------------
+Bugfixes:
+- Fixed client-side encoding when using ISO-8859-1 as content type instead of UTF-8.
+
+
+Version 0.3 (26.08.2007):
+-------------------------------
+Changes:
+- Changed integration interfaces thereby losing backwards compatibility.
+- Repackaged chat as standalone, phpBB2 and phpBB3 versions.
+- Added simple backend to manage users and channels for standalone version.
+
+
+Version 0.3.1 (03.09.2007):
+-------------------------------
+New features:
+- Added chat version for integration with the Simple Machines Forum.
+
+Bugfixes:
+- Fixed phpBB integration for usernames containing the ampersand ("&") which phpBB stores as HTML entity ("&amp;").
+
+Other changes:
+- Updated SQL queries to use a given database connection identifier.
+- Added calls to free the memory used by the database calls as soon as possible.
+
+
+Version 0.3.1.1 (05.09.2007):
+-------------------------------
+Bugfixes:
+- Fixed handling of channels with apostrophe (') in their names.
+
+Changed files:
+- lib/class/Chat.php (all versions)
+
+
+Version 0.3.1.2 (06.09.2007):
+-------------------------------
+New features:
+- Added russian localization - thanks to SkyKnight.
+
+
+Version 0.3.2 (07.09.2007):
+-------------------------------
+New features:
+- Added greek localization - thanks to panas.
+
+Other changes:
+- Updated database table creation script to use utf8 as default charset and collation.
+
+Notes:
+- To update your existing database tables you can use the following SQL commands:
+ ALTER TABLE ajax_chat_online CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
+ ALTER TABLE ajax_chat_messages CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
+ ALTER TABLE ajax_chat_bans CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
+
+
+Version 0.4 (17.09.2007):
+-------------------------------
+New features:
+- Added support for BBCode.
+- Added new emoticons.
+- Improved replaceEmoticons method - it's now very easy to add custom emoticons.
+- Improved breakLongWords method.
+- Improved support for page encodings other than UTF-8.
+- Easier interface to add custom (IRC style) commands.
+- Integrated the style switching functionality with the ajaxChat object.
+
+Bugfixes:
+- Check if a session language is available before including it.
+- Stopped moderators from being able to kick admins or other moderators.
+- Removing non-whitespace control characters on server side (could lead to invalid XHTML).
+- Added Cache control headers on server side to better support IE.
+- Check if document.cookie is set in the style switcher readCookie method.
+- Clearing the chatlist and online users list with DOM methods instead of innerHTML="".
+The latter produced in conjunction with the content type application/xhtml+xml errors with Safari.
+
+
+Version 0.4.0.1 (17.09.2007):
+-------------------------------
+New features:
+- Added finnish localization - thanks to zazu.
+- Added AJAX Chat version for PunBB.
+- Login to phpBB2, phpBB3, PunBB and SMF via chat login and redirect to the chat.
+
+Bugfixes:
+- Password field in login form had been of type "text" instead of type "password".
+
+
+Version 0.5 (12.10.2007):
+-------------------------------
+New features:
+- Realtime monitoring and server-side log viewer replaces log files creation.
+- Invitation system to invite users to the current channel.
+- Private channels based on invitation system.
+- Possibility to access restricted channels by invitation.
+- Possibility to use persistent font colors.
+- Client-side settings are stored persistently in a settings cookie.
+- /me and /describe and /action (new) messages are displayed in a custom style class.
+- Added config variable to limit the number of available cannels.
+- Added config variable to define the max users logged in.
+- Added config variable to enable/disable private messages.
+- Added config variable to enable/disable private channels.
+- Added config variable to force auto-login.
+- Added config variables to adjust guest usernames.
+- Added config variable to enable/disable the display of channel messages login/logout, channel enter/leave.
+- Added config variables to define the time of day and the days in the week the chat is opened.
+- Styles from different chat versions are now included in all packages.
+- Restructured CSS styles to separate Positioning, Borders, Fonts and Colors.
+- Restructured DataBase code and added support for MySQLi.
+- Chat versions with forum integration now use the existing database connection.
+- Improved (multibyte) encoding support.
+
+Bugfixes:
+- Several (10) XMLHttpRequest objects are created for POST requests to allow real asynchronism.
+ This way messages sent before the server could respond don't result in an error message anymore.
+- JavaScript links (private message links in online list) were not escaped properly.
+- Removed Byte Order Mark at the beginning of finnish language files which caused unwanted output.
+- Session handling now allows to keep the current session on logout.
+
+Other changes:
+- Code refactoring to cleanup the code and avoid naming collisions.
+- Removed PHP Code from Template files - using a simple template system with custom tags.
+- License change => Creative Commons Attribution-Share Alike (still free and open source).
+
+Changed files:
+- all (all versions)
+
+
+Version 0.5.0.1 (13.10.2007):
+-------------------------------
+Changes:
+- Moved forum integration code out of class files and into lib/custom.php.
+
+
+Version 0.5.1 (14.10.2007):
+-------------------------------
+New features:
+- Added simple flood control (two new config variables).
+
+Bugfixes:
+- Ignored userNames were not escaped properly for message filter query [SECURITY RISK].
+- /roll messages were being displayed as user messages instead of chatBot messages (Code refactoring mistake).
+- No display of invitations/uninvitations or /roll messages from ignored users.
+- Preventing robots from being logged in automatically (phpBB3 version).
+
+
+Version 0.5.1.1 (16.10.2007):
+-------------------------------
+Bugfixes:
+- Non-ASCII characters didn't work in JavaScript links with IE and Opera - fixed.
+
+Other changes:
+- Changed file extension of the template files to html.
+- The chat now tries to send a logout request on unload of the chat window.
+
+
+Version 0.5.1.2 (16.10.2007):
+-------------------------------
+Bugfixes:
+- Sometimes it could happen that the same message was added twice on client side - fixed.
+
+Other changes:
+- Removed the logout request on chat window unload again - logout on reload is too much of a drawback.
+
+Notes:
+- Due to the bugfix, the parameters of the addMessageToChatList and onNewMessage methods changed.
+
+
+Version 0.5.1.3 (17.10.2007):
+-------------------------------
+Bugfixes:
+- Some SQL queries used were not compatible with MySQL ANSI and ANSI_QUOTES SQL Modes - fixed.
+
+
+Version 0.5.1.4 (18.10.2007):
+-------------------------------
+Bugfixes:
+- Somehow a bug crept into the invitations code - fixed.
+
+New features:
+- Added hebrew localization - thanks to Smiley Barry.
+- Updated finnish localization - thanks to zazu.
+- Updated greek localization - thanks to panas.
+
+
+Version 0.5.1.5 (18.10.2007):
+-------------------------------
+New features:
+- Added AJAX Chat version for MyBB.
+- Added new style "MyBB".
+
+
+Version 0.5.2 (20.10.2007):
+-------------------------------
+New features:
+- Added arabic localization - thanks to pepotiger (www.dd4bb.com).
+- Added better support for bidirectional text ("dir" attribute).
+
+Bugfixes:
+- The strings replacing the language tags had not been HTML-encoded - fixed.
+- Fixed a bug preventing guest logins (empty password) with Opera.
+
+Other changes:
+- Using "&#8203;" (zero width space) as default string to wrap long words.
+
+
+Version 0.5.2.1 (20.10.2007):
+-------------------------------
+New features:
+- Updated dutch localization - thanks to Nic Mertens.
+- The dateTime display is now better configurable.
+- Adding a new JS config option listing settings to be excluded from being stored in a session cookie.
+
+
+Version 0.5.2.2 (23.10.2007):
+-------------------------------
+
+Bugfixes:
+- Fixing the "Only variables should be assigned by reference" notice in standalone version on PHP4.
+- Fixing the "cannot yet handle MBCS in html_entity_decode()" warning on PHP4.
+ Due to PHP bug #25670, html_entity_decode does not work with UTF-8 for PHP versions < 5.
+- Improved the entity encoding/decoding handling.
+
+Changed files:
+- lib/class/AJAXChat.php (all versions)
+- lib/class/CustomAJAXChat.php (standalone version)
+
+
+Version 0.5.3 (05.11.2007):
+-------------------------------
+New features:
+- Added possibility to configure if messages are shown which have been sent prior to the user entering the channel.
+- Updated russian localization - thanks to SkyKnight.
+
+Bugfixes:
+- Fixed background-color and horizontal stretch of chatlist for IE6.
+
+
+Version 0.5.3.1 (05.11.2007):
+-------------------------------
+
+Bugfixes:
+- Fixed methods reference assignment for getChannels and getAllChannels (PHP4).
+
+Changed files:
+- lib/class/AJAXChat.php (all versions)
+- lib/class/CustomAJAXChat.php (all versions)
+
+
+Version 0.5.4 (06.11.2007):
+-------------------------------
+New features:
+- Added new JS config variable to enable/disable autofocus on the input field.
+- Added JS methods to add custom initialization and finalization code.
+
+
+Version 0.5.4.1 (07.11.2007):
+-------------------------------
+Bugfixes:
+- The session is now started automatically if not already started.
+ The useless sessionCreateNew config variable has been removed accordingly.
+- Removed the duplicate #ajaxChatContent #ajaxChatMessageText entry in shoutbox CSS file.
+
+
+Version 0.5.5 (09.11.2007):
+-------------------------------
+New features:
+- Updated italian locale - thanks to s8s8.
+
+Bugfixes:
+- Replaced the unreliable navigator.cookieEnabled check with a custom JS method.
+
+Other changes:
+- The shoutbox class now skips session handling and database connections and has been reduced to parse and return the shoutbox template.
+- Shoutbox users are logged in with the first AJAX request.
+- Current user information (ID, Name) is now gathered through AJAX requests using the info messages interface.
+
+
+Version 0.5.6 (11.11.2007):
+-------------------------------
+New features:
+- Added romanian locale - thanks to K.Z. (kamikaze666).
+
+Other changes:
+- Code refactoring to improve the functional and modular design.
+- Added an interface class to push messages to the chat or query user data.
+
+
+Version 0.5.6.1 (12.11.2007):
+-------------------------------
+New features:
+- Added swedish locale - thanks to Eric.
+
+
+Version 0.6 (13.11.2007):
+-------------------------------
+New features:
+- Added support for ipv6 (only on PHP5 and not on windows hosts).
+
+Bugfixes:
+- The Chat URL had not been HTML encoded for the template output - fixed.
+- Logged-in forum users providing a password on the login form had been directed to the forum - fixed.
+
+Other Changes:
+- Updated database table creation script to support ipv6 storage.
+- Improved handling with multiple databases.
+- Renamed tag FORUM_URL to FORUM_LOGIN_URL to avoid confusion.
+
+Notes:
+- It is recommended to recreate the chat tables to avoid conflicts with old IP entries.
+
+
+Version 0.6.0.1 (14.11.2007):
+-------------------------------
+Bugfixes:
+- IPs were not escaped properly for storage - fixed.
+
+Other Changes:
+- Added code to suppress warnings if converting the IPs to or from storage format fails.
+
+
+Version 0.6.1 (17.11.2007):
+-------------------------------
+New features:
+- Added slovak locale - thanks to Peter.
+- The own userName and the current channelName are displayed bold when using /who and /list commands.
+- Added possibility to search for IPs using the logs view (Search strings starting with "ip=", e.g. "ip=127.0.0.1").
+- Added client-side method "replaceCustomBBCode" to add more complex custom BBCodes.
+- Added client-side and server-side method "replaceCustomText" to replace any custom text.
+- Added new request variable "lang" to set the content language (e.g. "lang=en").
+- Added a language selection to the templates.
+
+Bugfixes:
+- Fixed bad JS usage of for...in loops for arrays which could lead to conflicts with JS frameworks.
+- Fixed misarranged display on IE6 for RTL direction languages (arabian, hebrew).
+- Fixed error name "errorCookiesRequired" in swedish JS language file which had been still "cookiesRequired".
+
+Other Changes:
+- Reduced required database queries to retrieve online users data.
+- Improved handling of private channels.
+- Added two new config variables to define the prefix and suffix of private channels.
+- Added a new config variable to define language names for the language selection.
+- The language setting is now saved in an extra cookie instead of the chat session.
+
+
+Version 0.6.2 (20.11.2007):
+-------------------------------
+New features:
+- Added AJAX Chat version for vBulletin.
+- Added new style "vBulletin".
+- Added four new config variables to set session cookie parameters.
+- Added CSS style for print layout.
+
+Other Changes:
+- Added language selection to the logs view template.
+- Updated slovak localization.
+- Changed config name sessionValuePrefix to sessionKeyPrefix (as it is a prefix for the key, not the value).
+- Restructured CSS files to import positions, borders, fonts and miscellaneous from separate files.
+
+
+Version 0.6.2.1 (28.11.2007):
+-------------------------------
+New features:
+- Added french locale - thanks to Ettelcar.
+
+Bugfixes:
+- Updated template file loggedOut.html to ensure valid XHTML (input tags must be put inside a block element).
+
+
+Version 0.6.3 (30.11.2007):
+-------------------------------
+New features:
+- Chat session is now tied to the forum session for the forum integration versions.
+
+Bugfixes:
+- Corrected typing error in french JavaScript localization file.
+
+
+Version 0.6.3.1 (02.12.2007):
+-------------------------------
+Bugfixes:
+- IE cannot handle CSS import rules using a media declaration (e.g. "print") - using inline media declaration instead.
+
+
+Version 0.7 (11.01.2008):
+-------------------------------
+New features:
+- Added optional Flash based sound support.
+- Added optional Flash based support to push udates over a socket connection.
+- Added extended user menu for the online list and the inline user listing (/who command).
+- Added client-side settings page.
+- Added option document title blinking on new messages.
+- Extended the input field to a multiline textarea (line break can be entered by SHIFT+ENTER).
+- Added a message length counter.
+- Added the possibility to delete messages.
+- Added possibility to search for userIDs using the logs view (Search strings starting with "userID=", e.g. "userID=123").
+- Added ukraine localization - thanks to Yuriy Smetana.
+- Added bulgarian localization - thanks to Borislav Manolov.
+- Added norwegian localization - thanks to DagArneKirkerod.
+
+Other changes:
+- License change => GNU Affero General Public License (still free and open source).
+- Added the private channel of registered users to the channel listing.
+- Made the current userRole accessible on client side.
+- Made the current channelID accessible on client side.
+- Removed the inclusion of js/custom.js from the logs and loggedOut template.
+- Moved CSS rules for "body" into the templates, to avoid Flash conflicts on style switching.
+- Improved logs view update handling.
+- Improved JS config options handling.
+- Improved IE5-6 style.
+- The commands are now separated into single methods on client and server side.
+- Added possibility to force "text/html" content-type.
+- Removed the /me command as it had no real use.
+- Users exceeding the maxMessageRate are not banned anymore, they get an error message instead.
+- Kicked users get automatically banned for the time in minutes set as defaultBanTime.
+
+Bugfixes:
+- MyBB admin/moderator authentication didn't work properly if user belonged to multiple usergroups - fixed.
+- Fixed PREG Unicode related bug in the trimString method - thanks to Fiery_Fenix.
+- Fixed a bug related to the alternating rowClass and the maxMessages setting - thanks to Frug for the info.
+- If the IP of an Admin had been banned he could not login - fixed.
+
+
+Version 0.7.0.1 (12.01.2008):
+-------------------------------
+New features:
+- A click on a username in the chatlist now adds the name to the input field.
+
+Other changes:
+- Closing current query automatically if the query userName is not found (logged out, changed nick).
+- Adding a query close message before another query is opened.
+
+
+Version 0.7.0.2 (14.01.2008):
+-------------------------------
+Changes:
+- Updated french and italian localizations - thanks to Massimiliano Tiraboschi.
+
+Bugfixes:
+- The logs view updated too slow if not in monitor mode and with enabled socket connection - fixed.
+
+
+Version 0.7.1 (15.01.2008):
+-------------------------------
+New features:
+- Added the (optional and limited) possibility for registered users to access the logs view.
+- Added serbian localization - thanks to Saša Stojanović.
+
+Bugfixes:
+- The soundVolume selection always showed the first option on page reload - fixed.
+- Fixed a small display error for inserted logout messages.
+- Adjusted the code font size for the print view.
+
+
+Version 0.7.1.1 (16.01.2008):
+-------------------------------
+Changes:
+- Reflecting the setting allowUserMessageDelete on client-side.
+- Made the channelID of each message accessible on client-side.
+- Allowing users to delete messages received privately or posted in their own private channel.
+
+Bugfixes:
+- Fixed a bug which made bans of registered users ineffective - thanks to Seether for the info.
+- Fixed a naming bug affecting the defaultBanTime config value - thanks to Seether for the info.
+- Fixed a bug which prevented the "invalid channel message" from being displayed.
+- Added the missing join inside the client-side method assignFontColorToMessage - thanks to druiid for the info.
+
+
+Version 0.7.2 (18.01.2008):
+-------------------------------
+New features:
+- Added the possibility to serve multiple chat installations using the same socket server.
+- Added polish localization - thanks to Tomasz Topa.
+- Updated finnish localization - thanks to Asmo Soinio.
+- Updated russian localization - thanks to Dmitry Plyonkin.
+- Updated ukrainian localization - thanks to Yuriy Smetana.
+
+Other changes:
+- Removing deleted messages from the chatlist of all clients on the same channel.
+
+Bugfixes:
+- Catching errors when trying to play sounds on the settings page with no Flash plugin installed.
+
+
+Version 0.7.3 (29.01.2008):
+-------------------------------
+New features:
+- Added new client-side config option ajaxChatConfig.startChatOnLoad to delay the chat update.
+- Added possibility to retrieve teaser content without being logged in to the chat view.
+- Updated bulgarian localization - thanks to Borislav Manolov.
+
+Other changes:
+- Made the userID available for the method ajaxChat.getCustomUserMenuItems(encodedUserName, userID).
+- Related to the bugfix the online list is now always visible on chat load.
+
+Bugfixes:
+- If the chat window was just closed the online list would be always hidden on next chat load - fixed.
+- Added a workaraound for an IE bug happening on guest logins with the MyBB integration version.
+
+
+Version 0.7.4 (29.02.2008):
+-------------------------------
+New features:
+- Added an installation script (install.php) to create the database tables.
+ Make sure you delete this file after installation!
+- Updated ukrainian localization - thanks to Yuriy Smetana.
+- Updated greek localization - thanks to Akis Panas.
+
+Bugfixes:
+- Admin could not login if the chat was closed - fixed.
+- Added missing userID to a getUserNodeStringItems call - thanks to Xavier Gouley.
+- Fixed a bug (this.dom[id] instead of domNode) in updateDOM method - thanks to Xavier Gouley.
+- Made sure the database is selected on CustomAJAXChatInterface usage of SMF version.
+
+
+Version 0.8 (05.03.2008):
+-------------------------------
+New features:
+- Improved socket code which allows real streaming of chat messages and greatly improves performance.
+- Moved ignore list code to client-side making it possible to store ignored users using the settings cookie.
+- Added client-side interface to parse input text and input commands before sending it to server-side.
+- Added chinese (simplified) locale - thanks to mikespook.
+
+Other changes:
+- Changed invitation code to work with the new socket code.
+- Improved the online status and session handling.
+
+Bugfixes:
+- Added two missing JavaScript language strings for userName error messages.
+
+Notes:
+- The chat messages delivered using the socket connection are not encrypted even if the Chat-URL is on HTTPS.
+- A new database table for the invitations has been added.
+ To update your existing database you can use the following SQL command:
+ CREATE TABLE ajax_chat_invitations (
+ userID INT(11) NOT NULL,
+ channel INT(11) NOT NULL,
+ dateTime DATETIME NOT NULL
+ ) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+
+Version 0.8.1 (09.03.2008):
+-------------------------------
+New features:
+- Added image BBCode support (can be disabled via user settings).
+- Added new client-side settings to enable/disable image and font color BBCode.
+- Added new JavaScript config setting to define allowed soure URL's for media content (e.g. images).
+- Added Português (Brasil) locale - thanks to vitoalvaro.
+
+Bugfixes:
+- Added a type check for a given database connection object (MySQL vs. MySQLi).
+- The method AJAXChat->getChatURL() could return the URL with the port added twice - fixed.
+
+Other changes:
+- Removed the 'mysql' setting for the versions for forums without MySQLi support (now detected automatically).
+
+
+Version 0.8.1.1 (10.03.2008):
+-------------------------------
+Bugfixes:
+- Fixed an Opera bug related to the display of the deletion link for chat messages.
+
+
+Version 0.8.1.2 (22.03.2008):
+-------------------------------
+New features:
+- Added Turkish locale - thanks to Cydonian.
+
+Bugfixes:
+- Accessing the chat via HTTPS produced an encryption warning on IE due to the hardcoded flash codebase url - fixed.
+
+
+Version 0.8.2 (27.02.2009):
+-------------------------------
+New features:
+- Added status icon to indicate when chat is waiting for a response from the server (orange) or when chat is idle (green).
+- Clicking the status icon will force the chat client to retry (workaround for when there is a lost connection).
+- Added Catalan locale - thanks to Manu Quintans.
+- Added Japanese locale - thanks to Ocean.
+- Added Croatian locale - thanks to Renato.
+- Added Korean locale - thanks to Sangho Choi.
+- Added Slovenian locale - thanks to Valter Pepelko.
+- Added Chinese (Traditional) locale - thanks to Tiffblue.
+- Added Indonesian locale - thanks to Edi Muljadi.
+- Added Czech locale - thanks to Fredy.
+- Updated Swedish localization - thanks to Eric.
+- Updated Spanish localization - thanks to Manu Quintans.
+
+Bugfixes:
+- Inline user menus will no longer expand hidden below the chat window.
+- Replacing the accept method of the server socket with the non-blocking accept_nonblock.
+- Hyphen in database table names should no longer cause an error (in standalone chat client only).
+- Fixed a typo in the Greek translation - thanks to Marios Zindilis.
+- Posting an image should no longer break the autoscroll on slow connections or when it is not cached.
+- Blank username and password will now log in correctly with a guest number in the standalone client.
+
+
+Version 0.8.3 (26.06.2009):
+-------------------------------
+New features:
+- Added Hungarian localization - thanks to Atag and Molnár Tamás.
+- Added Welsh localization - thanks to Alan Davies.
+- Added Estonian localization - thanks to Alar Sapelkov.
+- Added Galician localization - thanks to Ruth.
+- Added Georgian localization - thanks to Giorgi Maghlakelidze.
+- Updated French localization - thanks to Xytovl.
+- Updated Finnish localization - thanks to Saku Laukkanen.
+- Nicer looking status icons.
+- Status icon turns red when there is connection trouble.
+- Chat will now automatically attempt to reconnect to the server if the connection is lost, rather than dying silently.
+- Chat now uses a buffer before performing multiple DOM operations. This should give a noticeable speed improvement when the
+chat list updates many messages at once (such as when viewing logs). - thanks to varamin.
+
+Bugfixes:
+- The invite, uninvite, and whereis user menu options will now only appear in the inline user menu.
+- Rolled back the database name handling change because of too many conflicts. If your database has a hyphen in it, you should
+check the AJAXChatDataBase.php file to see the commented line.
+
+
+Version 0.8.4 (15.02.2012):
+-------------------------------
+Bugfixes:
+- Fix to remove javascript error message in Chrome when initializing flash bridge.
+
+Changed files:
+- js/FABridge.js (all versions) - thanks to many users for this one.
+
+
+Version 0.8.5 (20.01.2012):
+-------------------------------
+New features:
+- Added Danish localization. - thanks to Allan Rehhoff.
+- Added easier to navigate html readme file.
+- PHPBB3 html readme file now includes proper custom instructions on implementing a shoutbox.
+
+Bugfixes:
+- Another fix to reintroduce sound in chrome - thanks to jsebean.
+
+
+Version 0.8.5a (11.05.2012):
+-------------------------------
+Bugfixes:
+- Fixed a typo in config.php that would cause chat to crash if used. (all versions)
+
+
+Version 0.8.6 (21.10.2012):
+-------------------------------
+New features:
+- Added Thai localization - thanks to Norrapat Nimmanee.
+- Added Macedonian localization - thanks to the jedi nebojsa.
+- Added Farsi localization - thanks to mahmood sajjadi.
+- Added Portuguese (Portugal) localization - thanks to Broas.
+- Install.php checks to see if config.php has been created before running (standalone).
+
+Bugfixes:
+- Improved Brazilian Portuguese translation - thanks to Pedro Innecco (all versions)
+- Corrected some language codes (all versions)
+- Improved Dutch translation - thanks to Dimitri Taghon (all versions)
+- Fixed misplaced estonian language files. (all versions)
+- Fixed a typo in the localization section of config.php (all versions)
+
+
+Version 0.8.7 (1.10.2014)
+-------------------------------
+Notice:
+- Minimum php version is now 5 (was 4).
+- phpbb2 branch discontinued.
+- License has changed from GNU Affero to a Modified MIT License. See file included in download.
+
+New features:
+- Added normal Dutch localization (moved existing nl to nl-be) - thanks to Patrick Donker.
+- Hide shoutbox input for users without write permissions - thanks to Felix Eckhofer.
+- Added a /clear command to clear the chatlist of all text - thanks to Borislav Manolov.
+
+Bugfixes:
+- Updated Russian and Norwegian localizations - thanks to Il'ya A. Lykov.
+- Methods called statically are now declared as static to meet php 5.4 strict standards.
+- Fixed case when messages were not displayed to users on page load if last message was deleted - thanks to KEMBL KEMBL.
+- Fixed exploit using img tag to pass text request var.
+- Change preg_replace with /e to preg_replace_callback in AJAXChatTemplate.php - thanks to Jan Kröpke.
+- Fixed browser crashing bug with certain long words - thanks to Clint.
+- Properly detect and report mysqli connection errors.
+- Fixed a case where the default channel could be blocked from the limitChannelList config option.
+- Fix potential conflict between php and mysql timezones by using mysql's FROM_UNIXTIME(). - thanks to ManOnDaMoon.
+- Normalized sound volumes a bit.
+- Fixed mybb integration database connection. Connection details should be pulled automatically now.
+- Fidex mybb integration guest logins to accept guests that don't enter a username (assign numbers like other versions). \ No newline at end of file
diff --git a/library/ajaxchat/chat/chat.sql b/library/ajaxchat/chat/chat.sql
new file mode 100644
index 000000000..5e7efea35
--- /dev/null
+++ b/library/ajaxchat/chat/chat.sql
@@ -0,0 +1,47 @@
+
+DROP TABLE IF EXISTS ajax_chat_online;
+CREATE TABLE ajax_chat_online (
+ userID INT(11) NOT NULL,
+ userName VARCHAR(64) NOT NULL,
+ userRole INT(1) NOT NULL,
+ channel INT(11) NOT NULL,
+ dateTime DATETIME NOT NULL,
+ ip VARBINARY(16) NOT NULL,
+ PRIMARY KEY (userID),
+ INDEX (userName)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+DROP TABLE IF EXISTS ajax_chat_messages;
+CREATE TABLE ajax_chat_messages (
+ id INT(11) NOT NULL AUTO_INCREMENT,
+ userID INT(11) NOT NULL,
+ userName VARCHAR(64) NOT NULL,
+ userRole INT(1) NOT NULL,
+ channel INT(11) NOT NULL,
+ dateTime DATETIME NOT NULL,
+ ip VARBINARY(16) NOT NULL,
+ text TEXT,
+ PRIMARY KEY (id),
+ INDEX message_condition (id, channel, dateTime),
+ INDEX (dateTime)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+DROP TABLE IF EXISTS ajax_chat_bans;
+CREATE TABLE ajax_chat_bans (
+ userID INT(11) NOT NULL,
+ userName VARCHAR(64) NOT NULL,
+ dateTime DATETIME NOT NULL,
+ ip VARBINARY(16) NOT NULL,
+ PRIMARY KEY (userID),
+ INDEX (userName),
+ INDEX (dateTime)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+DROP TABLE IF EXISTS ajax_chat_invitations;
+CREATE TABLE ajax_chat_invitations (
+ userID INT(11) NOT NULL,
+ channel INT(11) NOT NULL,
+ dateTime DATETIME NOT NULL,
+ PRIMARY KEY (userID, channel),
+ INDEX (dateTime)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
diff --git a/library/ajaxchat/chat/css/Cobalt.css b/library/ajaxchat/chat/css/Cobalt.css
new file mode 100644
index 000000000..08c4e363b
--- /dev/null
+++ b/library/ajaxchat/chat/css/Cobalt.css
@@ -0,0 +1,122 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by PunBB style "Cobalt":
+ * http://punbb.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#1a1a1a;
+ color:#ababab;
+ border: 0;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ background-color:#383838;
+ color:#ababab;
+ border: 1px solid #565656;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#2A2A2A;
+ color:#D4D4D4;
+ }
+ #loginContent h1 {
+ color:#D4D4D4;
+ }
+ #loginContent a {
+ color:#60A0DC;
+ }
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#424242;
+ color:#D4D4D4;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+
+ #content {
+ background-color:#2A2A2A;
+ color:#D4D4D4;
+ }
+ #content h1 {
+ color:#D4D4D4;
+ }
+ #content a {
+ color:#60A0DC;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer {
+ border: 1px solid #565656;
+ background-color:#383838;
+ }
+ #content #bbCodeContainer, #content #emoticonsContainer {
+ background-color:#383838;
+ padding: 5px;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#565656;
+ }
+ #content .rowOdd {
+ background-color:#484848;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#D4D4D4;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#60A0DC;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#60A0DC;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#383838;
+ color:#D4D4D4;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Core.css b/library/ajaxchat/chat/css/Core.css
new file mode 100644
index 000000000..104fb1b8a
--- /dev/null
+++ b/library/ajaxchat/chat/css/Core.css
@@ -0,0 +1,115 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by Simple Machines Forum style "SMF Default Theme - Core":
+ * http://www.simplemachines.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#CDE7FF;
+ color:#333333;
+ border: 1px solid #787878;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #787878;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ #loginContent {
+ background-color:#E5E5E8;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#000;
+ }
+ #loginContent a {
+ color:#000;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#E5E5E8;
+ color:#000;
+ }
+ #content h1 {
+ color:#000;
+ }
+ #content a {
+ color:#000;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#FFF;
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content #emoticonsContainer {
+ border-color:#ADADAD;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#ECEDF3;
+ }
+ #content .rowOdd {
+ background-color:#F6F6F6;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#0000FF;
+ }
+ #content .admin {
+ color:#FF0000;
+ }
+ #content .chatBot {
+ color:#476C8E;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#476C8E;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#88A6C0;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Lithium.css b/library/ajaxchat/chat/css/Lithium.css
new file mode 100644
index 000000000..877615838
--- /dev/null
+++ b/library/ajaxchat/chat/css/Lithium.css
@@ -0,0 +1,116 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by PunBB style "Lithium":
+ * http://punbb.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#6C8A3F;
+ color: #fff;
+ border: 1px solid #6C8A3F;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #6C8A3F;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #loginContent h1 {
+ color:#333333;
+ }
+ #loginContent a {
+ color:#638137;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#333333;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #content h1 {
+ color:#333333;
+ }
+ #content a {
+ color:#638137;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:#6C8A3F;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#F1F1F1;
+ }
+ #content .rowOdd {
+ background-color:#DEDFDF;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#638137;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#638137;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#6C8A3F;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Mercury.css b/library/ajaxchat/chat/css/Mercury.css
new file mode 100644
index 000000000..f7e12d53f
--- /dev/null
+++ b/library/ajaxchat/chat/css/Mercury.css
@@ -0,0 +1,154 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by PunBB style "Mercury":
+ * http://punbb.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ #content input, #content select, #content textarea {
+ border: 1px solid #565656;
+ }
+ #content textarea {
+ border-color: #383838;
+ }
+ #content input {
+ border-radius: 3px;
+ }
+ #loginContent {
+ background-color:#2A2A2A;
+ color:#D4D4D4;
+ }
+ #loginContent h1 {
+ color:#D4D4D4;
+ }
+ #loginContent a {
+ color:#F6B620;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#424242;
+ border-color:#565656;
+ color:#D4D4D4;
+ }
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#424242;
+ color:#D4D4D4;
+ border-radius: 3px;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+
+ #content {
+ background-color:#2A2A2A;
+ color:#D4D4D4;
+ }
+ #content h1 {
+ color:#D4D4D4;
+ }
+ #content a {
+ color:#F6B620;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#383838;
+ color:#D4D4D4;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content #emoticonsContainer {
+ border: 0;
+ background-color:#383838;
+ }
+ #content #colorCodesContainer {
+ padding: 5px;
+ box-shadow: 2px 2px 4px #000;
+ border-radius: 3px;
+ }
+ #content #onlineListContainer {
+ background: #383838;
+ }
+ #content #onlineListContainer #onlineList div {
+ margin: 0 1px 1px 1px;
+ border-radius: 5px;
+ background: #404040;
+ }
+ #content #onlineListContainer #onlineList ul {
+ margin-top: 1px;
+ list-style: none;
+ }
+ #content #emoticonsContainer {
+ border-radius: 3px;
+ }
+ #content #bbCodeContainer {
+ border: 0; padding-left: 0;
+ }
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton {
+ background-color:#383838;
+ color:#D4D4D4;
+ }
+ #content #bbCodeContainer input:hover, #content #logoutButton:hover, #content #submitButton:hover {
+ background-color:#565656;
+ }
+ #content #optionsContainer input.button {
+ border: 0;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#505050;
+ }
+ #content .rowOdd {
+ background-color:#484848;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#D4D4D4;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#F6B620;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#F6B620;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ color:#D4D4D4;
+ height: 15px;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/MyBB.css b/library/ajaxchat/chat/css/MyBB.css
new file mode 100644
index 000000000..9daa19d56
--- /dev/null
+++ b/library/ajaxchat/chat/css/MyBB.css
@@ -0,0 +1,115 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by MyBB style "MyBB Default":
+ * http://www.mybboard.net/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#02619f;
+ color:#fff;
+ font-weight: bold;
+ border: 0px solid #02619f;
+ border-radius: 5px;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #02619f;
+ border-radius: 5px;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+ #loginContent {
+ background-color:#FFF;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#000;
+ }
+ #loginContent a {
+ color:#000;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#FFF;
+ color:#000;
+ }
+ #content h1 {
+ color:#000;
+ }
+ #content a {
+ color:#000;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#FFF;
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content #emoticonsContainer {
+ border-color:#ADADAD;
+ background-color:#E5E5E8;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven, #content .rowOdd {
+ background-color:#EFEFEF;
+ border-bottom: 1px solid #bdccf7;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#0000FF;
+ }
+ #content .admin {
+ color:#FF0000;
+ }
+ #content .chatBot {
+ color:#476C8E;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#476C8E;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#02619f;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Oxygen.css b/library/ajaxchat/chat/css/Oxygen.css
new file mode 100644
index 000000000..916317483
--- /dev/null
+++ b/library/ajaxchat/chat/css/Oxygen.css
@@ -0,0 +1,116 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by PunBB style "Oxygen":
+ * http://punbb.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#0066B9;
+ color: #fff;
+ border: 1px solid #0066B9;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #0066B9;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #loginContent h1 {
+ color:#333333;
+ }
+ #loginContent a {
+ color:#0066B9;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#333333;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #content h1 {
+ color:#333333;
+ }
+ #content a {
+ color:#0066B9;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:#0066B9;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#F1F1F1;
+ }
+ #content .rowOdd {
+ background-color:#DEDFDF;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#0066B9;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#0066B9;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#0066B9;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Plum.css b/library/ajaxchat/chat/css/Plum.css
new file mode 100644
index 000000000..a1aec9fde
--- /dev/null
+++ b/library/ajaxchat/chat/css/Plum.css
@@ -0,0 +1,112 @@
+/*
+ * @package AJAX_Chat
+ * @author Rosina Ramirez
+ * @copyright (c) Rosina Ramirez
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ #content input, select, #content textarea, #loginButton {
+ border: 0; box-shadow:1px 1px 4px 0px rgba(0,0,0,0.5);
+ }
+ #content textarea { border-color: #383838; }
+ #content input, #loginButton { border-radius: 8px; }
+ #loginContent, #content {
+ background-color:#2A112F;
+ color:#9765A0;
+ }
+ a {
+ color:#DA83A1;
+ }
+ input, select {
+ background:#17081a;
+ border: 1px solid rgba(0,0,0,1);
+ color:#9765A0;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ h1 {
+ color:#CDA6D2;
+ }
+
+ #content textarea {
+ background:rgba(0,0,0,0.3);
+ color:#9765A0;
+ }
+ #content #chatList{
+ background: url('plum_images/plum.png') no-repeat bottom right rgba(0,0,0,0.3);
+ }
+ #content #colorCodesContainer {
+ padding: 5px;
+ box-shadow: 2px 2px 4px #000;
+ border-radius: 3px;
+ background:rgba(225,225,225,0.2)
+ }
+ #content #onlineListContainer, #content #helpContainer, #content #settingsContainer {
+ background: url('plum_images/plum2.png') no-repeat bottom left rgba(0,0,0,0.3);
+ }
+ #content #onlineListContainer #onlineList ul {
+ list-style: none;
+ }
+ #content #emoticonsContainer { border-radius: 3px; }
+ #content #bbCodeContainer { border: 0; padding-left: 0; }
+ #content #statusIconContainer { background-image: url('../img/loading-sprite.png'); }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginButton {
+ background-color:#461124;
+ color:#DAABBC;
+ }
+ #content #bbCodeContainer input:hover, #content #logoutButton:hover, #content #submitButton:hover, #loginButton:hover {
+ background-color:#591E33;
+ }
+ #content #optionsContainer input.button { border: 0; }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background:rgba(0,0,0,0.2);
+ }
+ #content .rowOdd {
+ background:rgba(0,0,0,0.3);
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#CDA6D2;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#CDA6D2;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ color:#CDA6D2;
+ height: 15px;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Sulfur.css b/library/ajaxchat/chat/css/Sulfur.css
new file mode 100644
index 000000000..f7d721ccf
--- /dev/null
+++ b/library/ajaxchat/chat/css/Sulfur.css
@@ -0,0 +1,116 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by PunBB style "Sulfur":
+ * http://punbb.org/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#B84623;
+ color: #fff;
+ border: 1px solid #B84623;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #B84623;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #loginContent h1 {
+ color:#333333;
+ }
+ #loginContent a {
+ color:#B84623;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#333333;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#F1F1F1;
+ color:#333333;
+ }
+ #content h1 {
+ color:#333333;
+ }
+ #content a {
+ color:#B84623;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:#B84623;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#F1F1F1;
+ }
+ #content .rowOdd {
+ background-color:#DEDFDF;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#B84623;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#B84623;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#B84623;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/Uranium.css b/library/ajaxchat/chat/css/Uranium.css
new file mode 100644
index 000000000..7ff9b648d
--- /dev/null
+++ b/library/ajaxchat/chat/css/Uranium.css
@@ -0,0 +1,178 @@
+/*
+ * @package AJAX_Chat
+ * @author Rosina Ramirez
+ * @copyright (c) Rosina Ramirez
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ input, select, textarea, #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content .rowEven,
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3, #content #inputFieldContainer, #loginContent input
+ { border-radius: 5px; -webkit-border-radius:5px;border:0;}
+ #loginContent a {
+ color:#4c9546;
+ }
+ #content #inputFieldContainer{height:46px; background:#0E0E0E;padding:0;}
+ #content #inputFieldContainer #inputField{box-shadow: inset 1px 1px 5px 1px #000; border:0;height: 40px;padding: 3px 0.5%;width: 99%;}
+ #content #inputFieldContainer #inputField:focus{outline:none;box-shadow:0px 0px 8px 1px #376e34;}
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#424242;
+ color:#b0b8a8;
+ border-radius: 3px;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+
+ #content, #loginContent {
+ background-color: #464646;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#464646), to(#181818));
+ background-image: -webkit-linear-gradient(top, #464646, #181818);
+ background-image: -moz-linear-gradient(top, #464646, #181818);
+ background-image: -o-linear-gradient(top, #464646, #181818);
+ background-image: linear-gradient(to bottom, #464646, #181818);
+ color:#b0b8a8;
+ }
+ h1, h3 {
+ color:#e2e9db;
+ text-shadow: 1px 1px 2px #191919;
+ }
+ #content a {
+ color:#4c9546;
+ }
+ #loginContent input, #loginContent select{background:#171717; color:#b0b8a8;}
+ input, select{padding: 3px;}
+ #content input,#content select,#content textarea {
+ background-color:#0e0e0e;
+ color:#b0b8a8;
+ }
+ #content #colorCodesContainer,#content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #inputFieldContainer,
+ #loginContent input[type=text], #loginContent input[type=password]{
+ box-shadow: 0px 0px 8px 1px #495a49; -webkit-box-shadow: 0px 0px 8px 1px #495a49;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer {
+ background-color:#171717;
+ border:0;
+ }
+ #content #chatList:after, #content #chatList:before{
+ content:'';
+ display:block;
+ position:absolute;
+ border-radius: 5px;
+ }
+ #content #chatList:before{top:17px;left:0px;width:0px;height:98%;box-shadow: 1px 0px 8px 1px #000;}
+ #content #chatList:after{top:0px;left:17px;width:98%;height:0px;box-shadow: 0px 1px 8px 1px #000;}
+
+ #content #onlineListContainer #onlineList div {
+ margin: 0 1px 1px 1px;
+ background: none;
+ }
+ #content #onlineListContainer #onlineList ul {
+ margin-top: 1px;
+ list-style: none;
+ }
+
+ #content #helplist table, #content #settingsList table{border-spacing:0;}
+ #content #emoticonsContainer { border-radius: 3px; }
+ #content #bbCodeContainer { border: 0; padding-left: 0; }
+ #content #statusIconContainer { background-image: url('../img/loading-sprite.png'); }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+ #content #bbCodeContainer input {
+ background-color: #d8ffd6;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d8ffd6), to(#467a44));
+ background-image: -webkit-linear-gradient(top, #d8ffd6, #467a44);
+ background-image: -moz-linear-gradient(top, #d8ffd6, #467a44);
+ background-image: -o-linear-gradient(top, #d8ffd6, #467a44);
+ background-image: linear-gradient(to bottom, #d8ffd6, #467a44);
+ color:#1d1d1d;
+ }
+ #content #bbCodeContainer input:hover{
+ background-color: #ffffff;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#08ff35));
+ background-image: -webkit-linear-gradient(top, #ffffff, #08ff35);
+ background-image: -moz-linear-gradient(top, #ffffff, #08ff35);
+ background-image: -o-linear-gradient(top, #ffffff, #08ff35);
+ background-image: linear-gradient(to bottom, #ffffff, #08ff35);
+ }
+ #content #bbCodeContainer input:active, #content #logoutButton:active, #content #submitButton:active, #loginContent #loginButton:active{box-shadow:0px 0px 8px 1px #38ff56;}
+ #content #logoutButton, #content #submitButton,#loginContent #loginButton{
+ background-color: #4fff58;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#4fff58), to(#194221));
+ background-image: -webkit-linear-gradient(top, #4fff58, #194221);
+ background-image: -moz-linear-gradient(top, #4fff58, #194221);
+ background-image: -o-linear-gradient(top, #4fff58, #194221);
+ background-image: linear-gradient(to bottom, #4fff58, #194221);
+ font-weight:bold; color:#fff;
+ text-shadow:0px 0px 5px #000;
+ }
+ #content #logoutButton:hover, #content #submitButton:hover, #loginContent #loginButton:hover{
+ background-color: #99ffa8;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#99ffa8), to(#002405));
+ background-image: -webkit-linear-gradient(top, #99ffa8, #002405);
+ background-image: -moz-linear-gradient(top, #99ffa8, #002405);
+ background-image: -o-linear-gradient(top, #99ffa8, #002405);
+ background-image: linear-gradient(to bottom, #99ffa8, #002405);
+ }
+
+ #content #colorCodesContainer{
+ border:0;
+ background:rgba(0,0,0,0.7);
+ padding:7px;
+ }
+ #content #colorCodesContainer a{border-radius:10px; box-shadow:0px 0px 3px 1px rgba(255,255,255,0.3); margin:0 5px;border:0;}
+ #content #optionsContainer input.button { border: 0; padding: 0; margin-right: 5px;}
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#131413;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#b0b8a8;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#4c9546;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#4c9546;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color: #171717;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3b6c37), to(#171717));
+ background-image: -webkit-linear-gradient(top, #3b6c37, #223220, #171717);
+ background-image: -moz-linear-gradient(top, #3b6c37, #223220, #171717);
+ background-image: -o-linear-gradient(top, #3b6c37, #223220, #171717);
+ background-image: linear-gradient(to bottom, #3b6c37, #223220, #171717);
+ }
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/beige.css b/library/ajaxchat/chat/css/beige.css
new file mode 100644
index 000000000..7c30bbe6d
--- /dev/null
+++ b/library/ajaxchat/chat/css/beige.css
@@ -0,0 +1,114 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#d9ce72;
+ color:#333333;
+ border: 1px solid #c8b360;
+ background-image: linear-gradient(to bottom, #d9ce72, #e1d995);
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #c8b360;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#F7F5DC;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#000;
+ }
+ #loginContent a {
+ color:#000;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#000;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#eee9be;
+ color:#000;
+ }
+ #content h1 {
+ color:#000;
+ }
+ #content a {
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:gray;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#FFFFF0;
+ }
+ #content .rowOdd {
+ background-color:#F7F5DC;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#FF6600;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#1E90FF;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#FFFFF0;
+ color:#000;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/black.css b/library/ajaxchat/chat/css/black.css
new file mode 100644
index 000000000..292b5d10c
--- /dev/null
+++ b/library/ajaxchat/chat/css/black.css
@@ -0,0 +1,115 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#000;
+ color:#f0f0f0;
+ border: 1px solid #808080;
+ background-image: linear-gradient(to bottom, #222, #000);
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ background-color:#000;
+ color:#fafafa;
+ border: 1px solid #808080;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#000;
+ color:#FFF;
+ }
+ #loginContent h1 {
+ color:#FFF;
+ }
+ #loginContent a {
+ color:#FFF;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#212121;
+ color:#FFF;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#000;
+ color:#FFF;
+ }
+ #content h1 {
+ color:#FFF;
+ }
+ #content a {
+ color:#FFF;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:gray;
+ background-color:#000;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#212121;
+ }
+ #content .rowOdd {
+ background-color:#000;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#FFF;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#FF6600;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#1E90FF;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#212121;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/fonts.css b/library/ajaxchat/chat/css/fonts.css
new file mode 100644
index 000000000..e12f628cc
--- /dev/null
+++ b/library/ajaxchat/chat/css/fonts.css
@@ -0,0 +1,100 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+/* Fonts */
+#loginContent {
+ font-family:Verdana, Arial, Helvetica, sans-serif;
+ font-size:0.8em;
+}
+#loginContent h1 {
+ font-size:1.3em;
+ font-family:"Trebuchet MS", Verdana, Arial, sans-serif;
+ font-weight:bold;
+}
+#loginContent a {
+ text-decoration:none;
+}
+#loginContent a:hover {
+ text-decoration:underline;
+}
+#loginContent #loginRegisteredUsers {
+ font-size:0.8em;
+}
+#loginContent #copyright {
+ font-size:0.8em;
+}
+#content {
+ font-family:Verdana, Arial, Helvetica, sans-serif;
+ font-size:0.8em;
+}
+#content h1 {
+ font-size:1.3em;
+ font-family:"Trebuchet MS", Verdana, Arial, sans-serif;
+ font-weight:bold;
+}
+#content h3 {
+ font-size:1.0em;
+}
+#content a {
+ text-decoration:none;
+}
+#content a:hover {
+ text-decoration:underline;
+}
+#content #copyright {
+ font-size:0.8em;
+}
+#content #chatList span.dateTime {
+ font-size:0.7em;
+}
+#content #chatList span.guest {
+ font-weight:bold;
+}
+#content #chatList span.user {
+ font-weight:bold;
+}
+#content #chatList span.moderator {
+ font-weight:bold;
+}
+#content #chatList span.admin {
+ font-weight:bold;
+}
+#content #chatList span.chatBot {
+ font-weight:bold;
+ font-style:italic;
+}
+#content #chatList .chatBotMessage {
+ font-style:italic;
+}
+#content #chatList .chatBotErrorMessage {
+ font-style:italic;
+}
+#content #chatList .privmsg {
+ font-style:italic;
+}
+#content #chatList .action {
+ font-style:italic;
+}
+#content #chatList q {
+ font-variant:small-caps;
+}
+#content #chatList code {
+ font-size:1.2em;
+}
+#content #onlineListContainer #onlineList div {
+ font-size:0.9em;
+}
+#content #helpContainer #helpList td {
+ font-size:0.9em;
+}
+#content #helpContainer #helpList td.code {
+ font-style:italic;
+}
+#content #settingsContainer #settingsList td {
+ font-size:0.9em;
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/global.css b/library/ajaxchat/chat/css/global.css
new file mode 100644
index 000000000..eff916fc9
--- /dev/null
+++ b/library/ajaxchat/chat/css/global.css
@@ -0,0 +1,278 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+/* Positioning */
+#loginContent {
+ position:absolute;
+ width:100%;
+ height:100%;
+}
+#loginContent #loginHeadlineContainer {
+ margin: 100px 100px 0 100px;
+}
+#loginContent #loginFormContainer, #loginContent #errorContainer {
+ margin: 0 100px;
+}
+#loginContent #loginFormContainer div {
+ margin-bottom:7px;
+}
+#loginContent #loginRegisteredUsers {
+ padding-top:5px;
+}
+#loginContent #copyright {
+ margin: 20px 100px 0 100px;
+}
+#content {
+ position:absolute;
+ width:100%;
+ height:100%;
+}
+#content #copyright {
+ position:absolute;
+ right:20px;
+ top:20px;
+}
+#content #headlineContainer {
+ position:absolute;
+ left:20px;
+ top:5px;
+}
+#content #logoutChannelContainer {
+ position:absolute;
+ left:20px;
+ top:50px;
+}
+#content #logoutChannelContainer select{
+ width: 105px;
+ height: 22px;
+}
+#content #statusIconContainer {
+ position:absolute;
+ right:20px;
+ top:50px;
+ width: 22px;
+ height: 22px;
+}
+#content #chatList {
+ position:absolute;
+ left:20px;
+ right:230px;
+ top:85px;
+ bottom:150px;
+ overflow:auto;
+}
+#content #inputFieldContainer {
+ position:absolute;
+ left:20px;
+ right:20px;
+ bottom:95px;
+ padding-right:4px;
+}
+#content #submitButtonContainer {
+ position:absolute;
+ right:20px;
+ bottom:60px;
+}
+#content #onlineListContainer {
+ position:absolute;
+ right:20px;
+ top:85px;
+ width:200px;
+ bottom:150px;
+}
+#content #helpContainer {
+ position:absolute;
+ right:20px;
+ top:85px;
+ width:360px;
+ bottom:150px;
+}
+#content #settingsContainer {
+ position:absolute;
+ right:20px;
+ top:85px;
+ width:360px;
+ bottom:150px;
+}
+#content #bbCodeContainer {
+ position:absolute;
+ left:20px;
+ bottom:20px;
+ padding:3px;
+}
+#content #colorCodesContainer {
+ position:absolute;
+ left:20px;
+ bottom:55px;
+ padding:3px;
+ z-index:1;
+}
+#content #emoticonsContainer {
+ position:absolute;
+ left:20px;
+ bottom:57px;
+ padding:3px;
+}
+#content #optionsContainer {
+ position:absolute;
+ right:20px;
+ bottom:20px;
+ padding:3px;
+ padding-right:0px;
+}
+#content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginContent #loginButton {
+ padding: 4px 10px;
+}
+#content #colorCodesContainer a {
+ display:block;
+ float:left;
+ width:20px;
+ height:20px;
+}
+#content #optionsContainer input {
+ vertical-align:middle;
+}
+#content #optionsContainer input.button {
+ width:22px;
+ height:22px;
+}
+#content #emoticonsContainer a {
+ margin-left:1px;
+ margin-right:1px;
+}
+#content #emoticonsContainer img {
+ vertical-align:middle;
+ margin-bottom:2px;
+}
+#content #headlineContainer h1 {
+ margin-left:auto;
+ margin-top:12px;
+}
+#content #chatList div {
+ padding: 2px 10px;
+}
+#content #chatList img {
+ vertical-align:middle;
+ margin-bottom:2px;
+}
+#content #chatList cite {
+ margin-right:5px;
+}
+#content #chatList .bbCodeImage {
+ vertical-align:top;
+ overflow:auto;
+ margin:5px;
+}
+#content #chatList .delete {
+ display:block;
+ float:right;
+ width:10px;
+ height:10px;
+ margin-top:2px;
+ padding-left:5px;
+ background:url('../img/delete.png') no-repeat right;
+}
+#content #inputFieldContainer #inputField {
+ width:100%;
+ height:40px;
+}
+#content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ height:30px;
+ padding: 4px 10px;
+ margin:0px;
+ text-align:center;
+}
+#content #onlineListContainer #onlineList, #content #helpContainer #helpList, #content #settingsContainer #settingsList {
+ position:absolute;
+ left:0px;
+ right:0px;
+ top:25px;
+ bottom:0px;
+ overflow:auto;
+}
+#content #onlineListContainer #onlineList div {
+ padding: 2px 10px;
+}
+#content #onlineListContainer #onlineList a {
+ display:block;
+}
+#content #onlineListContainer #onlineList ul {
+ margin: 5px 0;
+ padding-left:20px;
+}
+#content #helpContainer #helpList td, #content #settingsContainer #settingsList td {
+ padding: 4px 10px;
+ vertical-align:top;
+}
+#content #settingsContainer #settingsList td {
+ vertical-align:middle;
+}
+#content #settingsContainer #settingsList td.setting {
+ width:115px;
+}
+#content #settingsContainer #settingsList input.text {
+ width:100px;
+}
+#content #settingsContainer #settingsList select.left {
+ text-align:right;
+}
+#content #settingsContainer #settingsList input.button {
+ width:22px;
+ height:22px;
+ vertical-align:middle;
+ margin-bottom:2px;
+}
+
+/* Buttons */
+#content #optionsContainer #helpButton {
+ background:url('../img/help.png') no-repeat;
+}
+#content #optionsContainer #settingsButton {
+ background:url('../img/settings.png') no-repeat;
+}
+#content #optionsContainer #onlineListButton {
+ background:url('../img/users.png') no-repeat;
+}
+#content #optionsContainer #audioButton {
+ background:url('../img/audio.png') no-repeat 0px 0px;
+}
+#content #optionsContainer #audioButton.off {
+ background-position: 0px 100%;
+}
+#content #optionsContainer #autoScrollButton {
+ background:url('../img/autoscroll.png') no-repeat 0px 0px;
+}
+#content #optionsContainer #autoScrollButton.off {
+ background-position: 0px 100%;
+}
+#content #settingsContainer #settingsList input.playback {
+ background:url('../img/playback.png') no-repeat;
+}
+
+/* Borders */
+#content img {
+ border:none;
+}
+#content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer,
+#content #colorCodesContainer a, #content textarea {
+ border-width:1px;
+ border-style:solid;
+}
+#content #chatList .deleteSelected {
+ border-width:1px;
+ border-style:dotted;
+}
+#content #helpContainer #helpList table, #content #settingsContainer #settingsList table {
+ border-collapse:collapse;
+}
+
+/* Misc */
+#content #bbCodeContainer input, #content #optionsContainer input.button, #content #settingsContainer #settingsList input.button, #content #logoutButton, #content #submitButton, #loginContent #loginButton {
+ cursor:pointer;
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/grey.css b/library/ajaxchat/chat/css/grey.css
new file mode 100644
index 000000000..36d55d6a4
--- /dev/null
+++ b/library/ajaxchat/chat/css/grey.css
@@ -0,0 +1,115 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#8a8a8a;
+ color:#fff;
+ border: 1px solid #808080;
+ background-image: linear-gradient(to bottom, #8a8a8a, #444);
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ color:#333333;
+ border: 1px solid #808080;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Other Theme Elements */
+ #loginContent {
+ background-color:#F6F6F6;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#000;
+ }
+ #loginContent a {
+ color:#000;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#000;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#d0d0d0;
+ color:#000;
+ }
+ #content h1 {
+ color:#000;
+ }
+ #content a {
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea {
+ border-color:gray;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#FFF;
+ }
+ #content .rowOdd {
+ background-color:#F6F6F6;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#FF6600;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#1E90FF;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#FFF;
+ color:#000;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/ie5-6.css b/library/ajaxchat/chat/css/ie5-6.css
new file mode 100644
index 000000000..c6ddda3b6
--- /dev/null
+++ b/library/ajaxchat/chat/css/ie5-6.css
@@ -0,0 +1,70 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+
+/*
+ * Positioning adjustments for IE versions < 7
+ */
+
+body {
+ width:100%;
+ height:100%;
+}
+#content #chatList {
+ position:static;
+ margin-right:230px;
+ margin-left:20px;
+ margin-top:85px;
+ height:360px;
+}
+#content #onlineListContainer {
+ height:360px;
+}
+#content #helpContainer {
+ height:360px;
+}
+#content #settingsContainer {
+ height:360px;
+}
+#content #inputFieldContainer {
+ top:460px;
+ padding:0px;
+}
+#content #submitButtonContainer {
+ top:517px;
+}
+#content #bbCodeContainer {
+ top:550px;
+}
+#content #colorCodesContainer {
+ top:516px;
+}
+#content #emoticonsContainer {
+ top:517px;
+}
+#content #optionsContainer {
+ top:555px;
+}
+#content #inputFieldContainer #inputField {
+ width:94%;
+}
+#content #onlineListContainer #onlineList {
+ width:100%;
+ height:335px;
+ overflow:auto;
+}
+#content #helpContainer #helpList {
+ width:100%;
+ height:335px;
+ overflow:auto;
+}
+#content #settingsContainer #settingsList {
+ width:100%;
+ height:335px;
+ overflow:auto;
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/index.html b/library/ajaxchat/chat/css/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/css/index.html
diff --git a/library/ajaxchat/chat/css/plum_images/plum.png b/library/ajaxchat/chat/css/plum_images/plum.png
new file mode 100644
index 000000000..bd9f6ae6a
--- /dev/null
+++ b/library/ajaxchat/chat/css/plum_images/plum.png
Binary files differ
diff --git a/library/ajaxchat/chat/css/plum_images/plum2.png b/library/ajaxchat/chat/css/plum_images/plum2.png
new file mode 100644
index 000000000..b6c3b9011
--- /dev/null
+++ b/library/ajaxchat/chat/css/plum_images/plum2.png
Binary files differ
diff --git a/library/ajaxchat/chat/css/print.css b/library/ajaxchat/chat/css/print.css
new file mode 100644
index 000000000..a37857df6
--- /dev/null
+++ b/library/ajaxchat/chat/css/print.css
@@ -0,0 +1,114 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+
+/*
+ * Print layout
+ */
+
+@media print {
+
+ #content {
+ position:static;
+ }
+ #content #copyright {
+ display:none;
+ }
+ #content #headlineContainer {
+ display:none;
+ }
+ #content #logoutChannelContainer {
+ display:none;
+ }
+ #content #statusIconContainer {
+ display:none;
+ }
+ #content #chatList {
+ position:static;
+ overflow:visible;
+ }
+ #content #inputFieldContainer {
+ display:none;
+ }
+ #content #submitButtonContainer {
+ display:none;
+ }
+ #content #onlineListContainer {
+ display:none;
+ }
+ #content #helpContainer {
+ display:none;
+ }
+ #content #settingsContainer {
+ display:none;
+ }
+ #content #bbCodeContainer {
+ display:none;
+ }
+ #content #colorCodesContainer {
+ display:none;
+ }
+ #content #emoticonsContainer {
+ display:none;
+ }
+ #content #optionsContainer {
+ display:none;
+ }
+ #content #chatList div {
+ padding-bottom:5px;
+ }
+ #content #chatList img {
+ vertical-align:middle;
+ margin-bottom:2px;
+ }
+ #content #chatList cite {
+ margin-right:5px;
+ }
+ #content #chatList .delete {
+ display:none;
+ }
+
+ #content #chatList {
+ border:none;
+ }
+
+ #content {
+ font-family:'times new roman', times, serif;
+ font-size:1.0em;
+ text-align:justify;
+ }
+ #content #chatList code {
+ font-size:0.8em;
+ }
+
+ #content {
+ color:#000;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#FF6600;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#1E90FF;
+ }
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/prosilver.css b/library/ajaxchat/chat/css/prosilver.css
new file mode 100644
index 000000000..867c30d2d
--- /dev/null
+++ b/library/ajaxchat/chat/css/prosilver.css
@@ -0,0 +1,154 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by phpBB style "prosilver":
+ * http://www.phpbb.com/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Firefox button padding fix */
+ #content #bbCodeContainer input::-moz-focus-inner, #content #logoutButton::-moz-focus-inner, #content #submitButton::-moz-focus-inner {
+ border:0;
+ padding:0;
+ }
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#F7F5F1;
+ color:#333333;
+ border: 1px solid #8a8a8a;
+ background-image: linear-gradient(to bottom, #fafafa, #cdcdcd);
+ background-image: -webkit-linear-gradient(top, #fafafa, #cdcdcd);
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ background-color:#FFF;
+ color:#333333;
+ border: 1px solid #ababab;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ /* Headers */
+ #loginContent h1 {
+ color:#333333;
+ }
+ #content #headlineContainer h1 {
+ color: white;
+ margin-left: 20px;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#0c95d9;
+ color:#fff;
+ height: 25px;
+ }
+
+ /* Other Theme Elements */
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer {
+ border-color: #ababab;
+ }
+ #content #chatList .deleteSelected {
+ border-width:1px;
+ border-style:dotted;
+ }
+ #content #helpContainer #helpList table, #content #settingsContainer #settingsList table {
+ border-collapse:collapse;
+ }
+ #loginContent {
+ background-color:#F9F9F9;
+ color:#28313F;
+ }
+ #loginContent a {
+ color:#333333;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#333333;
+ }
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#F7F5F1;
+ color:#333333;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content #headlineContainer {
+ top: 0;
+ left: 0;
+ width: 100%;
+ background: #0c95d9;
+ }
+ #content #copyright, #content #copyright a {
+ color: white;
+ }
+ #content {
+ background-color:#F9F9F9;
+ color:#28313F;
+ }
+ #content a {
+ color:#333333;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content #emoticonsContainer {
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer {
+ box-shadow: 2px 2px 2px #777;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#eaf1f6;
+ }
+ #content .rowOdd {
+ background-color:#e1eaf2;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#333333;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:#AA0000;
+ }
+ #content .chatBot {
+ color:#D31141;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#D31141;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/shoutbox.css b/library/ajaxchat/chat/css/shoutbox.css
new file mode 100644
index 000000000..d22a92a74
--- /dev/null
+++ b/library/ajaxchat/chat/css/shoutbox.css
@@ -0,0 +1,168 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+
+/*
+ * Positioning
+ */
+#ajaxChatContent #ajaxChatChatList {
+ height:300px;
+ overflow:auto;
+}
+#ajaxChatContent #ajaxChatChatList div {
+ padding-left:5px;
+ padding-top:2px;
+ padding-right:5px;
+ padding-bottom:2px;
+}
+#ajaxChatContent #ajaxChatChatList img {
+ vertical-align:middle;
+ margin-bottom:2px;
+}
+#ajaxChatContent #ajaxChatChatList cite {
+ margin-right:5px;
+}
+#ajaxChatContent #ajaxChatChatList .bbCodeImage {
+ vertical-align:top;
+ overflow:auto;
+ margin:5px;
+}
+#ajaxChatContent #ajaxChatChatList .delete {
+ float:right;
+ width:10px;
+ height:10px;
+ margin-top:5px;
+ margin-left:5px;
+}
+#ajaxChatContent #ajaxChatInputFieldContainer #ajaxChatInputField {
+ width:90%;
+}
+#ajaxChatContent #ajaxChatCopyright {
+ margin-top:5px;
+}
+#ajaxChatContent #ajaxChatInputFieldContainer.write_forbidden {
+ display:none;
+}
+
+
+/*
+ * Borders
+ */
+
+#ajaxChatContent img {
+ border:none;
+}
+#ajaxChatContent #ajaxChatChatList .deleteSelected {
+ border-width:1px;
+ border-style:dotted;
+}
+
+
+/*
+ * Fonts
+ */
+
+#ajaxChatContent {
+ font-size:0.9em;
+}
+#ajaxChatContent a {
+ text-decoration:none;
+}
+#ajaxChatContent a:hover {
+ text-decoration:underline;
+}
+#ajaxChatContent #ajaxChatCopyright {
+ font-size:0.8em;
+}
+#ajaxChatContent #ajaxChatChatList span.dateTime {
+ font-size:0.7em;
+}
+#ajaxChatContent #ajaxChatChatList span.guest {
+ font-size:0.9em;
+ font-weight:bold;
+}
+#ajaxChatContent #ajaxChatChatList span.user {
+ font-size:0.9em;
+ font-weight:bold;
+}
+#ajaxChatContent #ajaxChatChatList span.moderator {
+ font-size:0.9em;
+ font-weight:bold;
+}
+#ajaxChatContent #ajaxChatChatList span.admin {
+ font-size:0.9em;
+ font-weight:bold;
+}
+#ajaxChatContent #ajaxChatChatList span.chatBot {
+ font-size:0.9em;
+ font-weight:bold;
+ font-style:italic;
+}
+#ajaxChatContent #ajaxChatList .chatBotMessage {
+ font-style:italic;
+}
+#ajaxChatContent #ajaxChatChatList .chatBotErrorMessage {
+ font-style:italic;
+}
+#ajaxChatContent #ajaxChatChatList .privmsg {
+ font-style:italic;
+}
+#ajaxChatContent #ajaxChatChatList .action {
+ font-style:italic;
+}
+#ajaxChatContent #ajaxChatChatList q {
+ font-variant:small-caps;
+}
+#ajaxChatContent #ajaxChatChatList code {
+ font-size:1.2em;
+}
+
+
+/*
+ * Colors
+ */
+
+#ajaxChatContent #ajaxChatChatList {
+ color:#000;
+}
+#ajaxChatContent #ajaxChatChatList {
+ background-color:#FFF;
+}
+#ajaxChatContent .rowEven {
+ background-color:#FFF;
+}
+#ajaxChatContent .rowOdd {
+ background-color:#F6F6F6;
+}
+#ajaxChatContent .guest {
+ color:gray;
+}
+#ajaxChatContent .user {
+ color:#000;
+}
+#ajaxChatContent .moderator {
+ color:#00AA00;
+}
+#ajaxChatContent .admin {
+ color:red;
+}
+#ajaxChatContent .chatBot {
+ color:#FF6600;
+}
+#ajaxChatContent #ajaxChatChatList .chatBotErrorMessage {
+ color:red;
+}
+#ajaxChatContent #ajaxChatChatList a {
+ color:#1E90FF;
+}
+#ajaxChatContent #ajaxChatChatList .delete {
+ background:url('../img/delete.png') no-repeat right;
+}
+#ajaxChatContent #ajaxChatChatList .deleteSelected {
+ border-color:red;
+}
diff --git a/library/ajaxchat/chat/css/subSilver.css b/library/ajaxchat/chat/css/subSilver.css
new file mode 100644
index 000000000..80f8b75b4
--- /dev/null
+++ b/library/ajaxchat/chat/css/subSilver.css
@@ -0,0 +1,117 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by phpBB style "subSilver":
+ * http://www.phpbb.com/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ #loginContent {
+ background-color:#E5E5E5;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#006699;
+ }
+ #loginContent a {
+ color:#000;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#FFF;
+ color:#000;
+ }
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#F7F5F1;
+ color:#000;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+
+ #content {
+ background-color:#E5E5E5;
+ color:#000;
+ }
+ #content h1 {
+ color:#006699;
+ }
+ #content a {
+ color:#000;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#FFF;
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content textarea{
+ border-color:#006699;
+ background-color:#FFF;
+ }
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton {
+ background-color:#F7F5F1;
+ color:#000;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#DEE3E7;
+ }
+ #content .rowOdd {
+ background-color:#EFEFEF;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#006600;
+ }
+ #content .admin {
+ color:#FFA34F;
+ }
+ #content .chatBot {
+ color:#DD6900;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#006699;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#DEE3E7;
+ color:#006699;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/subblack2.css b/library/ajaxchat/chat/css/subblack2.css
new file mode 100644
index 000000000..3043754aa
--- /dev/null
+++ b/library/ajaxchat/chat/css/subblack2.css
@@ -0,0 +1,117 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by phpBB style "subblack2":
+ * http://www.phpbb.com/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ #loginContent {
+ background-color:#000;
+ color:#FFFFCC;
+ }
+ #loginContent h1 {
+ color:#FFFFCC;
+ }
+ #loginContent a {
+ color:#FFFFCC;
+ }
+ #loginContent input, #loginContent select {
+ background-color:#212121;
+ color:#FFFFCC;
+ }
+ #loginContent #loginFormContainer #loginButton {
+ background-color:#212121;
+ color:#FFFFCC;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+
+ #content {
+ background-color:#000;
+ color:#FFFFCC;
+ }
+ #content h1 {
+ color:#CC9900;
+ }
+ #content a {
+ color:#FFFFCC;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#212121;
+ color:#FFFFCC;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #bbCodeContainer, #content #colorCodesContainer, #content #emoticonsContainer {
+ border-color:gray;
+ background-color:#212121;
+ }
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton {
+ background-color:#212121;
+ color:#FFFFCC;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#212121;
+ }
+ #content .rowOdd {
+ background-color:#000;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#FFFFCC;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#CC9900;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#FFCC00;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#212121;
+ color:#FFCC00;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/css/vBulletin.css b/library/ajaxchat/chat/css/vBulletin.css
new file mode 100644
index 000000000..91a7e1a7e
--- /dev/null
+++ b/library/ajaxchat/chat/css/vBulletin.css
@@ -0,0 +1,127 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Philip Nicolcev
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * Color palette inspired by vBulletin style "Standard-Style":
+ * http://www.vbulletin.com/
+ */
+
+@import url('global.css');
+@import url('fonts.css');
+@import url('print.css');
+
+@media screen,projection,handheld {
+
+ /* Buttons */
+ #content #bbCodeContainer input, #content #logoutButton, #content #submitButton, #loginForm #loginButton {
+ background-color:#7192A8;
+ color:#fff;
+ border: 0;
+ }
+ #content select, #loginForm select, #loginForm input, #content textarea {
+ background-color:#7192A8;
+ color:#fff;
+ border: 1px solid #2F4456;
+ }
+
+ /* Status Icon */
+ #content #statusIconContainer {
+ background-image: url('../img/loading-sprite.png');
+ }
+ #content .statusContainerOff {
+ background-position: 0px 0px;
+ }
+ #content .statusContainerOn {
+ background-position: 0px -22px;
+ }
+ #content .statusContainerAlert {
+ background-position: 0px -44px;
+ }
+
+ #loginContent {
+ background-color:#E1E1E2;
+ color:#000;
+ }
+ #loginContent h1 {
+ color:#3B5485;
+ }
+ #loginContent a {
+ color:#3B5485;
+ }
+ #loginContent #errorContainer {
+ color:red;
+ }
+ #content {
+ background-color:#E1E1E2;
+ color:#000;
+ }
+ #content #headlineContainer h1 {
+ color:#fff;
+ margin-left: 20px;
+ }
+ #content #headlineContainer {
+ top: 0;
+ left: 10px;
+ right: 10px;
+ background: #2F4456;
+ border-radius: 0px 0px 5px 5px;
+ }
+ #content #copyright, #content #copyright a {
+ color: white;
+ }
+ #content a {
+ color:#3B5485;
+ }
+ #content input, #content select, #content textarea {
+ background-color:#FFF;
+ color:#000;
+ }
+ #content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer {
+ border-color:#0B198C;
+ background-color:#FFF;
+ }
+ #content #colorCodesContainer a {
+ border-color:black;
+ }
+ #content #optionsContainer input {
+ background-color:transparent;
+ }
+ #content .rowEven {
+ background-color:#E1E4F2;
+ }
+ #content .rowOdd {
+ background-color:#F5F5FF;
+ }
+ #content .guest {
+ color:gray;
+ }
+ #content .user {
+ color:#000;
+ }
+ #content .moderator {
+ color:#00AA00;
+ }
+ #content .admin {
+ color:red;
+ }
+ #content .chatBot {
+ color:#3B5485;
+ }
+ #content #chatList .chatBotErrorMessage {
+ color:red;
+ }
+ #content #chatList a {
+ color:#3B5485;
+ }
+ #content #chatList .deleteSelected {
+ border-color:red;
+ }
+ #content #onlineListContainer h3, #content #helpContainer h3, #content #settingsContainer h3 {
+ background-color:#7192A8;
+ color:#FFF;
+ }
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/flash/FABridge.swf b/library/ajaxchat/chat/flash/FABridge.swf
new file mode 100644
index 000000000..1894cf489
--- /dev/null
+++ b/library/ajaxchat/chat/flash/FABridge.swf
Binary files differ
diff --git a/library/ajaxchat/chat/flash/index.html b/library/ajaxchat/chat/flash/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/flash/index.html
diff --git a/library/ajaxchat/chat/img/audio.png b/library/ajaxchat/chat/img/audio.png
new file mode 100644
index 000000000..fb3705316
--- /dev/null
+++ b/library/ajaxchat/chat/img/audio.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/autoscroll.png b/library/ajaxchat/chat/img/autoscroll.png
new file mode 100644
index 000000000..7c313e597
--- /dev/null
+++ b/library/ajaxchat/chat/img/autoscroll.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/delete.png b/library/ajaxchat/chat/img/delete.png
new file mode 100644
index 000000000..ae99c71a0
--- /dev/null
+++ b/library/ajaxchat/chat/img/delete.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/angel.png b/library/ajaxchat/chat/img/emoticons/angel.png
new file mode 100644
index 000000000..bf6abc421
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/angel.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/confused.png b/library/ajaxchat/chat/img/emoticons/confused.png
new file mode 100644
index 000000000..2616381b0
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/confused.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/cool.png b/library/ajaxchat/chat/img/emoticons/cool.png
new file mode 100644
index 000000000..e2a364881
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/cool.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/crying.png b/library/ajaxchat/chat/img/emoticons/crying.png
new file mode 100644
index 000000000..15a152a99
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/crying.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/devilish.png b/library/ajaxchat/chat/img/emoticons/devilish.png
new file mode 100644
index 000000000..8e2cd4584
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/devilish.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/eek.png b/library/ajaxchat/chat/img/emoticons/eek.png
new file mode 100644
index 000000000..07719a412
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/eek.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/error.png b/library/ajaxchat/chat/img/emoticons/error.png
new file mode 100644
index 000000000..3bbbb4a0d
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/error.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/favorite.png b/library/ajaxchat/chat/img/emoticons/favorite.png
new file mode 100644
index 000000000..3acb57dc9
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/favorite.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/glasses.png b/library/ajaxchat/chat/img/emoticons/glasses.png
new file mode 100644
index 000000000..d13f2c8c7
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/glasses.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/grin.png b/library/ajaxchat/chat/img/emoticons/grin.png
new file mode 100644
index 000000000..d15cf2d45
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/grin.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/help.png b/library/ajaxchat/chat/img/emoticons/help.png
new file mode 100644
index 000000000..f25fc3fbf
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/help.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/idea.png b/library/ajaxchat/chat/img/emoticons/idea.png
new file mode 100644
index 000000000..8851b99ba
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/idea.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/important.png b/library/ajaxchat/chat/img/emoticons/important.png
new file mode 100644
index 000000000..81e9ed29a
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/important.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/index.html b/library/ajaxchat/chat/img/emoticons/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/index.html
diff --git a/library/ajaxchat/chat/img/emoticons/kiss.png b/library/ajaxchat/chat/img/emoticons/kiss.png
new file mode 100644
index 000000000..8d3116dbd
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/kiss.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/monkey.png b/library/ajaxchat/chat/img/emoticons/monkey.png
new file mode 100644
index 000000000..d88f10b82
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/monkey.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/plain.png b/library/ajaxchat/chat/img/emoticons/plain.png
new file mode 100644
index 000000000..a6761bd10
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/plain.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/razz.png b/library/ajaxchat/chat/img/emoticons/razz.png
new file mode 100644
index 000000000..6430fd7ba
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/razz.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/sad.png b/library/ajaxchat/chat/img/emoticons/sad.png
new file mode 100644
index 000000000..8e6346a0b
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/sad.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/smile-big.png b/library/ajaxchat/chat/img/emoticons/smile-big.png
new file mode 100644
index 000000000..1617e019f
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/smile-big.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/smile.png b/library/ajaxchat/chat/img/emoticons/smile.png
new file mode 100644
index 000000000..d2313f19b
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/smile.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/surprise.png b/library/ajaxchat/chat/img/emoticons/surprise.png
new file mode 100644
index 000000000..d829a2640
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/surprise.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/warning.png b/library/ajaxchat/chat/img/emoticons/warning.png
new file mode 100644
index 000000000..a9e4ff399
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/warning.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/emoticons/wink.png b/library/ajaxchat/chat/img/emoticons/wink.png
new file mode 100644
index 000000000..46be68557
--- /dev/null
+++ b/library/ajaxchat/chat/img/emoticons/wink.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/help.png b/library/ajaxchat/chat/img/help.png
new file mode 100644
index 000000000..c67c7a60e
--- /dev/null
+++ b/library/ajaxchat/chat/img/help.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/index.html b/library/ajaxchat/chat/img/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/img/index.html
diff --git a/library/ajaxchat/chat/img/license.txt b/library/ajaxchat/chat/img/license.txt
new file mode 100644
index 000000000..4069d3a13
--- /dev/null
+++ b/library/ajaxchat/chat/img/license.txt
@@ -0,0 +1,45 @@
+
+The icons used for this project have been created by the
+
+=====================
+Tango Desktop Project
+=====================
+
+http://tango.freedesktop.org/
+
+
+Additional emoticons have been created by
+
+=============================
+zerwas2ky (KDE-Look.org user)
+=============================
+
+http://www.kde-look.org/content/show.php?content=65591
+
+
+The icons are licensed under the
+
+====================================================
+Creative Commons Attribution Share Alike 2.5 License
+====================================================
+
+http://creativecommons.org/licenses/by-sa/2.5/
+
+You are free:
+
+* to Share — to copy, distribute and transmit the work
+* to Remix — to adapt the work
+
+Under the following conditions:
+
+* Attribution.
+You must attribute the work in the manner specified by the author or licensor
+(but not in any way that suggests that they endorse you or your use of the work).
+
+* Share Alike.
+If you alter, transform, or build upon this work,
+you may distribute the resulting work only under the same or similar license to this one.
+
+- For any reuse or distribution, you must make clear to others the license terms of this work.
+- Any of the above conditions can be waived if you get permission from the copyright holder.
+- Nothing in this license impairs or restricts the author's moral rights.
diff --git a/library/ajaxchat/chat/img/loading-sprite.png b/library/ajaxchat/chat/img/loading-sprite.png
new file mode 100644
index 000000000..5d742145a
--- /dev/null
+++ b/library/ajaxchat/chat/img/loading-sprite.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/pixel.gif b/library/ajaxchat/chat/img/pixel.gif
new file mode 100644
index 000000000..e565824aa
--- /dev/null
+++ b/library/ajaxchat/chat/img/pixel.gif
Binary files differ
diff --git a/library/ajaxchat/chat/img/playback.png b/library/ajaxchat/chat/img/playback.png
new file mode 100644
index 000000000..10102d829
--- /dev/null
+++ b/library/ajaxchat/chat/img/playback.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/settings.png b/library/ajaxchat/chat/img/settings.png
new file mode 100644
index 000000000..cc91d6595
--- /dev/null
+++ b/library/ajaxchat/chat/img/settings.png
Binary files differ
diff --git a/library/ajaxchat/chat/img/users.png b/library/ajaxchat/chat/img/users.png
new file mode 100644
index 000000000..bced28cfb
--- /dev/null
+++ b/library/ajaxchat/chat/img/users.png
Binary files differ
diff --git a/library/ajaxchat/chat/index.php b/library/ajaxchat/chat/index.php
new file mode 100644
index 000000000..a7e2fd04e
--- /dev/null
+++ b/library/ajaxchat/chat/index.php
@@ -0,0 +1,24 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Suppress errors.
+error_reporting(0);
+
+// Path to the chat directory:
+define('AJAX_CHAT_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');
+
+// Include custom libraries and initialization code:
+require(AJAX_CHAT_PATH.'lib/custom.php');
+
+// Include Class libraries:
+require(AJAX_CHAT_PATH.'lib/classes.php');
+
+// Initialize the chat:
+$ajaxChat = new CustomAJAXChat();
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/install.php b/library/ajaxchat/chat/install.php
new file mode 100644
index 000000000..fd19e1beb
--- /dev/null
+++ b/library/ajaxchat/chat/install.php
@@ -0,0 +1,80 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Show all errors:
+error_reporting(E_ALL);
+
+// Remember to set up the config file to point to your database:
+file_exists('lib/config.php') or die('Failed to load lib/config.php. Did you remember to create a config file based on config.php.example?');
+
+// Path to the chat directory:
+define('AJAX_CHAT_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');
+
+// Include custom libraries and initialization code:
+require(AJAX_CHAT_PATH.'lib/custom.php');
+
+// Include Class libraries:
+require(AJAX_CHAT_PATH.'lib/classes.php');
+
+class CustomAJAXChatInstaller extends CustomAJAXChatInterface {
+
+ function &getDataBaseTableCreationQueries() {
+ $queries = array();
+ $index = 0;
+ // Retrieve the queries from the SQL file:
+ $lines = file(AJAX_CHAT_PATH.'chat.sql');
+ // Stop if an error occurs:
+ if(!$lines) {
+ echo 'Failed to load queries from file (chat.sql).';
+ die();
+ }
+ foreach($lines as $line) {
+ if(empty($line)) {
+ continue;
+ }
+ $line = trim($line);
+ if(count($queries) <= $index) {
+ array_push($queries, $line."\n");
+ } else {
+ $queries[$index] .= $line."\n";
+ }
+ // Create a new array item for each query:
+ if(substr($line, -1) == ';') {
+ $index++;
+ }
+ }
+ return $queries;
+ }
+
+ function createDataBaseTables($printSuccessConfirmation=true) {
+ $queries = $this->getDataBaseTableCreationQueries();
+ foreach($queries as $sql) {
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+ if($printSuccessConfirmation) {
+ // Print a success confirmation:
+ echo 'Database tables created successfully - please delete this file (install.php).';
+ }
+ }
+
+}
+
+// Initialize the chat installer:
+$ajaxChatInstaller = new CustomAJAXChatInstaller();
+
+// Create the database tables:
+$ajaxChatInstaller->createDataBaseTables();
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/FABridge.js b/library/ajaxchat/chat/js/FABridge.js
new file mode 100644
index 000000000..59424573b
--- /dev/null
+++ b/library/ajaxchat/chat/js/FABridge.js
@@ -0,0 +1,591 @@
+/*
+/*
+Copyright 2006 Adobe Systems Incorporated
+
+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.
+
+*/
+
+
+/*
+ * The Bridge class, responsible for navigating AS instances
+ */
+function FABridge(target,bridgeName)
+{
+ this.target = target;
+ this.remoteTypeCache = {};
+ this.remoteInstanceCache = {};
+ this.remoteFunctionCache = {};
+ this.localFunctionCache = {};
+ this.bridgeID = FABridge.nextBridgeID++;
+ this.name = bridgeName;
+ this.nextLocalFuncID = 0;
+ FABridge.instances[this.name] = this;
+ FABridge.idMap[this.bridgeID] = this;
+
+ return this;
+}
+
+// type codes for packed values
+FABridge.TYPE_ASINSTANCE = 1;
+FABridge.TYPE_ASFUNCTION = 2;
+
+FABridge.TYPE_JSFUNCTION = 3;
+FABridge.TYPE_ANONYMOUS = 4;
+
+FABridge.initCallbacks = {}
+
+FABridge.argsToArray = function(args)
+{
+ var result = [];
+ for (var i = 0; i < args.length; i++)
+ {
+ result[i] = args[i];
+ }
+ return result;
+}
+
+function instanceFactory(objID)
+{
+ this.fb_instance_id = objID;
+ return this;
+}
+
+function FABridge__invokeJSFunction(args)
+{
+ var funcID = args[0];
+ var throughArgs = args.concat();//FABridge.argsToArray(arguments);
+ throughArgs.shift();
+
+ var bridge = FABridge.extractBridgeFromID(funcID);
+ return bridge.invokeLocalFunction(funcID, throughArgs);
+}
+
+FABridge.addInitializationCallback = function(bridgeName, callback)
+{
+ var inst = FABridge.instances[bridgeName];
+ if (inst != undefined)
+ {
+ callback.call(inst);
+ return;
+ }
+
+ var callbackList = FABridge.initCallbacks[bridgeName];
+ if(callbackList == null)
+ {
+ FABridge.initCallbacks[bridgeName] = callbackList = [];
+ }
+
+ callbackList.push(callback);
+}
+
+function FABridge__bridgeInitialized(bridgeName) {
+ var objects = document.getElementsByTagName("object");
+ var ol = objects.length;
+ var activeObjects = [];
+ if (ol > 0) {
+ for (var i = 0; i < ol; i++) {
+ if (typeof objects[i].SetVariable != "undefined") {
+ activeObjects[activeObjects.length] = objects[i];
+ }
+ }
+ }
+ var embeds = document.getElementsByTagName("embed");
+ var el = embeds.length;
+ var activeEmbeds = [];
+ if (el > 0) {
+ for (var j = 0; j < el; j++) {
+ if (typeof embeds[j].SetVariable != "undefined") {
+ activeEmbeds[activeEmbeds.length] = embeds[j];
+ }
+ }
+ }
+ var aol = activeObjects.length;
+ var ael = activeEmbeds.length;
+ var searchStr = "bridgeName="+ bridgeName;
+ if ((aol == 1 && !ael) || (aol == 1 && ael == 1)) {
+ FABridge.attachBridge(activeObjects[0], bridgeName);
+ }
+ else if (ael == 1 && !aol) {
+ FABridge.attachBridge(activeEmbeds[0], bridgeName);
+ }
+ else {
+ var flash_found = false;
+ if (aol > 1) {
+ for (var k = 0; k < aol; k++) {
+ var params = activeObjects[k].childNodes;
+ for (var l = 0; l < params.length; l++) {
+ var param = params[l];
+ if (param.nodeType == 1 && param.tagName.toLowerCase() == "param" && param["name"].toLowerCase() == "flashvars" && param["value"].indexOf(searchStr) >= 0) {
+ FABridge.attachBridge(activeObjects[k], bridgeName);
+ flash_found = true;
+ break;
+ }
+ }
+ if (flash_found) {
+ break;
+ }
+ }
+ }
+ if (!flash_found && ael > 1) {
+ for (var m = 0; m < ael; m++) {
+ var flashVars = activeEmbeds[m].attributes.getNamedItem("flashVars").nodeValue;
+ if (flashVars.indexOf(searchStr) >= 0) {
+ FABridge.attachBridge(activeEmbeds[m], bridgeName);
+ break;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// used to track multiple bridge instances, since callbacks from AS are global across the page.
+
+FABridge.nextBridgeID = 0;
+FABridge.instances = {};
+FABridge.idMap = {};
+FABridge.refCount = 0;
+
+FABridge.extractBridgeFromID = function(id)
+{
+ var bridgeID = (id >> 16);
+ return FABridge.idMap[bridgeID];
+}
+
+FABridge.attachBridge = function(instance, bridgeName)
+{
+ var newBridgeInstance = new FABridge(instance, bridgeName);
+
+ FABridge[bridgeName] = newBridgeInstance;
+
+/* FABridge[bridgeName] = function() {
+ return newBridgeInstance.root();
+ }
+*/
+ var callbacks = FABridge.initCallbacks[bridgeName];
+ if (callbacks == null)
+ {
+ return;
+ }
+ for (var i = 0; i < callbacks.length; i++)
+ {
+ callbacks[i].call(newBridgeInstance);
+ }
+ delete FABridge.initCallbacks[bridgeName]
+}
+
+// some methods can't be proxied. You can use the explicit get,set, and call methods if necessary.
+
+FABridge.blockedMethods =
+{
+ toString: true,
+ get: true,
+ set: true,
+ call: true
+};
+
+FABridge.prototype =
+{
+
+
+// bootstrapping
+
+ root: function()
+ {
+ return this.deserialize(this.target.getRoot());
+ },
+//clears all of the AS objects in the cache maps
+ releaseASObjects: function()
+ {
+ return this.target.releaseASObjects();
+ },
+//clears a specific object in AS from the type maps
+ releaseNamedASObject: function(value)
+ {
+ if(typeof(value) != "object")
+ {
+ return false;
+ }
+ else
+ {
+ var ret = this.target.releaseNamedASObject(value.fb_instance_id);
+ return ret;
+ }
+ },
+//create a new AS Object
+ create: function(className)
+ {
+ return this.deserialize(this.target.create(className));
+ },
+
+
+ // utilities
+
+ makeID: function(token)
+ {
+ return (this.bridgeID << 16) + token;
+ },
+
+
+ // low level access to the flash object
+
+//get a named property from an AS object
+ getPropertyFromAS: function(objRef, propName)
+ {
+ if (FABridge.refCount > 0)
+ {
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
+ }
+ else
+ {
+ FABridge.refCount++;
+ retVal = this.target.getPropFromAS(objRef, propName);
+ retVal = this.handleError(retVal);
+ FABridge.refCount--;
+ return retVal;
+ }
+ },
+//set a named property on an AS object
+ setPropertyInAS: function(objRef,propName, value)
+ {
+ if (FABridge.refCount > 0)
+ {
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
+ }
+ else
+ {
+ FABridge.refCount++;
+ retVal = this.target.setPropInAS(objRef,propName, this.serialize(value));
+ retVal = this.handleError(retVal);
+ FABridge.refCount--;
+ return retVal;
+ }
+ },
+
+//call an AS function
+ callASFunction: function(funcID, args)
+ {
+ if (FABridge.refCount > 0)
+ {
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
+ }
+ else
+ {
+ FABridge.refCount++;
+ retVal = this.target.invokeASFunction(funcID, this.serialize(args));
+ retVal = this.handleError(retVal);
+ FABridge.refCount--;
+ return retVal;
+ }
+ },
+//call a method on an AS object
+ callASMethod: function(objID, funcName, args)
+ {
+ if (FABridge.refCount > 0)
+ {
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
+ }
+ else
+ {
+ FABridge.refCount++;
+ args = this.serialize(args);
+ retVal = this.target.invokeASMethod(objID, funcName, args);
+ retVal = this.handleError(retVal);
+ FABridge.refCount--;
+ return retVal;
+ }
+ },
+
+ // responders to remote calls from flash
+
+ //callback from flash that executes a local JS function
+ //used mostly when setting js functions as callbacks on events
+ invokeLocalFunction: function(funcID, args)
+ {
+ var result;
+ var func = this.localFunctionCache[funcID];
+
+ if(func != undefined)
+ {
+ result = this.serialize(func.apply(null, this.deserialize(args)));
+ }
+
+ return result;
+ },
+
+ // Object Types and Proxies
+
+ // accepts an object reference, returns a type object matching the obj reference.
+ getTypeFromName: function(objTypeName)
+ {
+ return this.remoteTypeCache[objTypeName];
+ },
+ //create an AS proxy for the given object ID and type
+ createProxy: function(objID, typeName)
+ {
+ var objType = this.getTypeFromName(typeName);
+ instanceFactory.prototype = objType;
+ var instance = new instanceFactory(objID);
+ this.remoteInstanceCache[objID] = instance;
+ return instance;
+ },
+ //return the proxy associated with the given object ID
+ getProxy: function(objID)
+ {
+ return this.remoteInstanceCache[objID];
+ },
+
+ // accepts a type structure, returns a constructed type
+ addTypeDataToCache: function(typeData)
+ {
+ newType = new ASProxy(this, typeData.name);
+ var accessors = typeData.accessors;
+ for (var i = 0; i < accessors.length; i++)
+ {
+ this.addPropertyToType(newType, accessors[i]);
+ }
+
+ var methods = typeData.methods;
+ for (var i = 0; i < methods.length; i++)
+ {
+ if (FABridge.blockedMethods[methods[i]] == undefined)
+ {
+ this.addMethodToType(newType, methods[i]);
+ }
+ }
+
+
+ this.remoteTypeCache[newType.typeName] = newType;
+ return newType;
+ },
+
+ //add a property to a typename; used to define the properties that can be called on an AS proxied object
+ addPropertyToType: function(ty, propName)
+ {
+ var c = propName.charAt(0);
+ var setterName;
+ var getterName;
+ if(c >= "a" && c <= "z")
+ {
+ getterName = "get" + c.toUpperCase() + propName.substr(1);
+ setterName = "set" + c.toUpperCase() + propName.substr(1);
+ }
+ else
+ {
+ getterName = "get" + propName;
+ setterName = "set" + propName;
+ }
+ ty[setterName] = function(val)
+ {
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, val);
+ }
+ ty[getterName] = function()
+ {
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
+ }
+ },
+
+ //add a method to a typename; used to define the methods that can be callefd on an AS proxied object
+ addMethodToType: function(ty, methodName)
+ {
+ ty[methodName] = function()
+ {
+ return this.bridge.deserialize(this.bridge.callASMethod(this.fb_instance_id, methodName, FABridge.argsToArray(arguments)));
+ }
+ },
+
+ // Function Proxies
+
+ //returns the AS proxy for the specified function ID
+ getFunctionProxy: function(funcID)
+ {
+ var bridge = this;
+ if (this.remoteFunctionCache[funcID] == null)
+ {
+ this.remoteFunctionCache[funcID] = function()
+ {
+ bridge.callASFunction(funcID, FABridge.argsToArray(arguments));
+ }
+ }
+ return this.remoteFunctionCache[funcID];
+ },
+
+ //reutrns the ID of the given function; if it doesnt exist it is created and added to the local cache
+ getFunctionID: function(func)
+ {
+ if (func.__bridge_id__ == undefined)
+ {
+ func.__bridge_id__ = this.makeID(this.nextLocalFuncID++);
+ this.localFunctionCache[func.__bridge_id__] = func;
+ }
+ return func.__bridge_id__;
+ },
+
+ // serialization / deserialization
+
+ serialize: function(value)
+ {
+ var result = {};
+
+ var t = typeof(value);
+ //primitives are kept as such
+ if (t == "number" || t == "string" || t == "boolean" || t == null || t == undefined)
+ {
+ result = value;
+ }
+ else if (value instanceof Array)
+ {
+ //arrays are serializesd recursively
+ result = [];
+ for (var i = 0; i < value.length; i++)
+ {
+ result[i] = this.serialize(value[i]);
+ }
+ }
+ else if (t == "function")
+ {
+ //js functions are assigned an ID and stored in the local cache
+ result.type = FABridge.TYPE_JSFUNCTION;
+ result.value = this.getFunctionID(value);
+ }
+ else if (value instanceof ASProxy)
+ {
+ result.type = FABridge.TYPE_ASINSTANCE;
+ result.value = value.fb_instance_id;
+ }
+ else
+ {
+ result.type = FABridge.TYPE_ANONYMOUS;
+ result.value = value;
+ }
+
+ return result;
+ },
+
+ //on deserialization we always check the return for the specific error code that is used to marshall NPE's into JS errors
+ // the unpacking is done by returning the value on each pachet for objects/arrays
+ deserialize: function(packedValue)
+ {
+
+ var result;
+
+ var t = typeof(packedValue);
+ if (t == "number" || t == "string" || t == "boolean" || packedValue == null || packedValue == undefined)
+ {
+ result = this.handleError(packedValue);
+ }
+ else if (packedValue instanceof Array)
+ {
+ result = [];
+ for (var i = 0; i < packedValue.length; i++)
+ {
+ result[i] = this.deserialize(packedValue[i]);
+ }
+ }
+ else if (t == "object")
+ {
+ for(var i = 0; i < packedValue.newTypes.length; i++)
+ {
+ this.addTypeDataToCache(packedValue.newTypes[i]);
+ }
+ for (var aRefID in packedValue.newRefs)
+ {
+ this.createProxy(aRefID, packedValue.newRefs[aRefID]);
+ }
+ if (packedValue.type == FABridge.TYPE_PRIMITIVE)
+ {
+ result = packedValue.value;
+ }
+ else if (packedValue.type == FABridge.TYPE_ASFUNCTION)
+ {
+ result = this.getFunctionProxy(packedValue.value);
+ }
+ else if (packedValue.type == FABridge.TYPE_ASINSTANCE)
+ {
+ result = this.getProxy(packedValue.value);
+ }
+ else if (packedValue.type == FABridge.TYPE_ANONYMOUS)
+ {
+ result = packedValue.value;
+ }
+ }
+ return result;
+ },
+ //increases the reference count for the given object
+ addRef: function(obj)
+ {
+ this.target.incRef(obj.fb_instance_id);
+ },
+ //decrease the reference count for the given object and release it if needed
+ release:function(obj)
+ {
+ this.target.releaseRef(obj.fb_instance_id);
+ },
+
+ // check the given value for the components of the hard-coded error code : __FLASHERROR
+ // used to marshall NPE's into flash
+
+ handleError: function(value)
+ {
+ if (typeof(value)=="string" && value.indexOf("__FLASHERROR")==0)
+ {
+ var myErrorMessage = value.split("||");
+ if(FABridge.refCount > 0 )
+ {
+ FABridge.refCount--;
+ }
+ throw new Error(myErrorMessage[1]);
+ return value;
+ }
+ else
+ {
+ return value;
+ }
+ }
+};
+
+// The root ASProxy class that facades a flash object
+
+ASProxy = function(bridge, typeName)
+{
+ this.bridge = bridge;
+ this.typeName = typeName;
+ return this;
+};
+//methods available on each ASProxy object
+ASProxy.prototype =
+{
+ get: function(propName)
+ {
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
+ },
+
+ set: function(propName, value)
+ {
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, value);
+ },
+
+ call: function(funcName, args)
+ {
+ this.bridge.callASMethod(this.fb_instance_id, funcName, args);
+ },
+
+ addRef: function() {
+ this.bridge.addRef(this);
+ },
+
+ release: function() {
+ this.bridge.release(this);
+ }
+};
diff --git a/library/ajaxchat/chat/js/chat.js b/library/ajaxchat/chat/js/chat.js
new file mode 100644
index 000000000..9a93f5e45
--- /dev/null
+++ b/library/ajaxchat/chat/js/chat.js
@@ -0,0 +1,2940 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ *
+ * The SELFHTML documentation has been used throughout this project:
+ * http://selfhtml.org
+ *
+ * Stylesheet and cookie methods have been inspired by Paul Sowden (A List Apart):
+ * http://www.alistapart.com/stories/alternate/
+ */
+
+// AJAX Chat client side logic:
+var ajaxChat = {
+
+ settingsInitiated: null,
+ styleInitiated: null,
+ initializeFunction: null,
+ finalizeFunction: null,
+ loginChannelID: null,
+ loginChannelName: null,
+ timerRate: null,
+ timer: null,
+ ajaxURL: null,
+ baseURL: null,
+ regExpMediaUrl: null,
+ dirs: null,
+ startChatOnLoad: null,
+ chatStarted: null,
+ domIDs: null,
+ dom: null,
+ settings: null,
+ nonPersistentSettings: null,
+ unusedSettings: null,
+ bbCodeTags: null,
+ colorCodes: null,
+ emoticonCodes: null,
+ emoticonFiles: null,
+ soundFiles: null,
+ sounds: null,
+ soundTransform: null,
+ sessionName: null,
+ cookieExpiration: null,
+ cookiePath: null,
+ cookieDomain: null,
+ cookieSecure: null,
+ chatBotName: null,
+ chatBotID: null,
+ allowUserMessageDelete: null,
+ inactiveTimeout: null,
+ privateChannelDiff: null,
+ privateMessageDiff: null,
+ showChannelMessages: null,
+ messageTextMaxLength: null,
+ socketServerEnabled: null,
+ socketServerHost: null,
+ socketServerPort: null,
+ socketServerChatID: null,
+ socket: null,
+ socketIsConnected: null,
+ socketTimerRate: null,
+ socketReconnectTimer: null,
+ socketRegistrationID: null,
+ userID: null,
+ userName: null,
+ userRole: null,
+ channelID: null,
+ channelName: null,
+ channelSwitch: null,
+ usersList: null,
+ userNamesList: null,
+ userMenuCounter: null,
+ encodedUserName: null,
+ userNodeString: null,
+ ignoredUserNames: null,
+ lastID: null,
+ localID: null,
+ lang: null,
+ langCode: null,
+ baseDirection: null,
+ originalDocumentTitle: null,
+ blinkInterval: null,
+ httpRequest: null,
+ retryTimer: null,
+ retryTimerDelay: null,
+ requestStatus: 'ok',
+ DOMbuffering: null,
+ DOMbuffer: null,
+ DOMbufferRowClass: 'rowOdd',
+
+ init: function(config, lang, initSettings, initStyle, initialize, initializeFunction, finalizeFunction) {
+ this.httpRequest = {};
+ this.usersList = [];
+ this.userNamesList = [];
+ this.userMenuCounter = 0;
+ this.lastID = 0;
+ this.localID = 0;
+ this.lang = lang;
+ this.initConfig(config);
+ this.initDirectories();
+ if(initSettings) {
+ this.initSettings();
+ }
+ if(initStyle) {
+ this.initStyle();
+ }
+ this.initializeFunction = initializeFunction;
+ this.finalizeFunction = finalizeFunction;
+ if(initialize) {
+ this.setLoadHandler();
+ }
+ },
+
+ initConfig: function(config) {
+ this.loginChannelID = config['loginChannelID'];
+ this.loginChannelName = config['loginChannelName'];
+ this.timerRate = config['timerRate'];
+ this.ajaxURL = config['ajaxURL'];
+ this.baseURL = config['baseURL'];
+ this.regExpMediaUrl = config['regExpMediaUrl'];
+ this.startChatOnLoad = config['startChatOnLoad'];
+ this.domIDs = config['domIDs'];
+ this.settings = config['settings'];
+ this.nonPersistentSettings = config['nonPersistentSettings'];
+ this.bbCodeTags = config['bbCodeTags'];
+ this.colorCodes = config['colorCodes'];
+ this.emoticonCodes = config['emoticonCodes'];
+ this.emoticonFiles = config['emoticonFiles'];
+ this.soundFiles = config['soundFiles'];
+ this.sessionName = config['sessionName'];
+ this.cookieExpiration = config['cookieExpiration'];
+ this.cookiePath = config['cookiePath'];
+ this.cookieDomain = config['cookieDomain'];
+ this.cookieSecure = config['cookieSecure'];
+ this.chatBotName = config['chatBotName'];
+ this.chatBotID = config['chatBotID'];
+ this.allowUserMessageDelete = config['allowUserMessageDelete'];
+ this.inactiveTimeout = config['inactiveTimeout'];
+ this.privateChannelDiff = config['privateChannelDiff'];
+ this.privateMessageDiff = config['privateMessageDiff'];
+ this.showChannelMessages = config['showChannelMessages'];
+ this.messageTextMaxLength = config['messageTextMaxLength'];
+ this.socketServerEnabled = config['socketServerEnabled'];
+ this.socketServerHost = config['socketServerHost'];
+ this.socketServerPort = config['socketServerPort'];
+ this.socketServerChatID = config['socketServerChatID'];
+ this.DOMbuffering = false;
+ this.DOMbuffer = "";
+ this.retryTimerDelay = (this.inactiveTimeout*6000 - this.timerRate)/4 + this.timerRate;
+ },
+
+ initDirectories: function() {
+ this.dirs = {};
+ this.dirs['emoticons'] = this.baseURL+'img/emoticons/';
+ this.dirs['sounds'] = this.baseURL+'sounds/';
+ this.dirs['flash'] = this.baseURL+'flash/';
+ },
+
+ initSettings: function() {
+ var cookie = this.readCookie(this.sessionName + '_settings'),
+ i, settingsArray, setting, key, value, number;
+ this.settingsInitiated = true;
+ this.unusedSettings = {};
+ if(cookie) {
+ settingsArray = cookie.split('&');
+ for(i=0; i<settingsArray.length; i++) {
+ setting = settingsArray[i].split('=');
+ if(setting.length === 2) {
+ key = setting[0];
+ value = this.decodeText(setting[1]);
+ switch(value) {
+ case 'true':
+ value = true;
+ break;
+ case 'false':
+ value = false;
+ break;
+ case 'null':
+ value = null;
+ break;
+ default:
+ number = parseFloat(value);
+ if(!isNaN(number)) {
+ if(parseInt(number) === number) {
+ value = parseInt(number);
+ } else {
+ value = number;
+ }
+ }
+ }
+ if(this.inArray(this.nonPersistentSettings, key)) {
+ // The setting is not used, store it for the persistSettings method:
+ this.unusedSettings[key] = value;
+ } else {
+ this.settings[key] = value;
+ }
+ }
+ }
+ }
+ },
+
+ persistSettings: function() {
+ var settingsArray;
+ if(this.settingsInitiated) {
+ settingsArray = [];
+ for(var property in this.settings) {
+ if(this.inArray(this.nonPersistentSettings, property)) {
+ if(this.unusedSettings && this.unusedSettings[property]) {
+ // Store the unusedSetting previously stored:
+ this.settings[property] = this.unusedSettings[property];
+ } else {
+ continue;
+ }
+ }
+ settingsArray.push(property + '=' + this.encodeText(this.settings[property]));
+ }
+ this.createCookie(this.sessionName + '_settings', settingsArray.join('&'), this.cookieExpiration);
+ }
+ },
+
+ getSettings: function() {
+ return this.settings;
+ },
+
+ getSetting: function(key) {
+ // Only return null if setting is null or undefined, not if it is false:
+ for(var property in this.settings) {
+ if(property === key) {
+ return this.settings[key];
+ }
+ }
+ return null;
+ },
+
+ setSetting: function(key, value) {
+ this.settings[key] = value;
+ },
+
+ initializeSettings: function() {
+ if(this.settings['persistFontColor'] && this.settings['fontColor']) {
+ // Set the inputField font color to the font color:
+ if(this.dom['inputField']) {
+ this.dom['inputField'].style.color = this.settings['fontColor'];
+ }
+ }
+ },
+
+ initialize: function() {
+ this.setUnloadHandler();
+ this.initializeDocumentNodes();
+ this.loadPageAttributes();
+ this.initEmoticons();
+ this.initColorCodes();
+ this.initializeSettings();
+ this.setSelectedStyle();
+ this.customInitialize();
+ //preload the Alert icon (it can't display if there's no connection unless it's cached!)
+ this.setStatus('retrying');
+ if(typeof this.initializeFunction === 'function') {
+ this.initializeFunction();
+ }
+ if(!this.isCookieEnabled()) {
+ this.addChatBotMessageToChatList('/error CookiesRequired');
+ } else {
+ if(this.startChatOnLoad) {
+ this.startChat();
+ } else {
+ this.setStartChatHandler();
+ this.requestTeaserContent();
+ }
+ }
+ },
+
+ requestTeaserContent: function() {
+ var params = '&view=teaser';
+ params += '&getInfos=' + this.encodeText('userID,userName,userRole');
+ if(!isNaN(parseInt(this.loginChannelID))) {
+ params += '&channelID='+this.loginChannelID;
+ } else if(this.loginChannelName !== null) {
+ params += '&channelName='+this.encodeText(this.loginChannelName);
+ }
+ this.updateChat(params);
+ },
+
+ setStartChatHandler: function() {
+ if(this.dom['inputField']) {
+ this.dom['inputField'].onfocus = function() {
+ ajaxChat.startChat();
+ // Reset the onfocus event on first call:
+ ajaxChat.dom['inputField'].onfocus = '';
+ };
+ }
+ },
+
+ startChat: function() {
+ this.chatStarted = true;
+ if(this.dom['inputField'] && this.settings['autoFocus']) {
+ this.dom['inputField'].focus();
+ }
+ this.loadFlashInterface();
+ this.startChatUpdate();
+ },
+
+ loadPageAttributes: function() {
+ var htmlTag = document.getElementsByTagName('html')[0];
+ this.langCode = htmlTag.getAttribute('lang') ? htmlTag.getAttribute('lang') : 'en';
+ this.baseDirection = htmlTag.getAttribute('dir') ? htmlTag.getAttribute('dir') : 'ltr';
+ },
+
+ setLoadHandler: function() {
+ // Make sure initialize() is called on page load:
+ var onload = window.onload;
+ if(typeof onload !== 'function') {
+ window.onload = function() {
+ ajaxChat.initialize();
+ };
+ } else {
+ window.onload = function() {
+ onload();
+ ajaxChat.initialize();
+ };
+ }
+ },
+
+ setUnloadHandler: function() {
+ // Make sure finalize() is called on page unload:
+ var onunload = window.onunload;
+ if(typeof onunload !== 'function') {
+ window.onunload = function() {
+ ajaxChat.finalize();
+ };
+ } else {
+ window.onunload = function() {
+ ajaxChat.finalize();
+ onunload();
+ };
+ }
+ },
+
+ updateDOM: function(id, str, prepend, overwrite) {
+ var domNode = this.dom[id] ? this.dom[id] : document.getElementById(id);
+ if(!domNode) {
+ return;
+ }
+ try {
+ // Test for validity before adding the string to the DOM:
+ domNode.cloneNode(false).innerHTML = str;
+ if(overwrite) {
+ domNode.innerHTML = str;
+ } else if(prepend) {
+ domNode.innerHTML = str + domNode.innerHTML;
+ } else {
+ domNode.innerHTML += str;
+ }
+ } catch(e) {
+ this.addChatBotMessageToChatList('/error DOMSyntax '+id);
+ this.updateChatlistView();
+ }
+ },
+
+ initializeDocumentNodes: function() {
+ this.dom = {};
+ for(var key in this.domIDs) {
+ this.dom[key] = document.getElementById(this.domIDs[key]);
+ }
+ },
+
+ initEmoticons: function() {
+ this.DOMbuffer = "";
+ for(var i=0; i<this.emoticonCodes.length; i++) {
+ // Replace specials characters in emoticon codes:
+ this.emoticonCodes[i] = this.encodeSpecialChars(this.emoticonCodes[i]);
+ this.DOMbuffer = this.DOMbuffer
+ + '<a href="javascript:ajaxChat.insertText(\''
+ + this.scriptLinkEncode(this.emoticonCodes[i])
+ + '\');"><img src="'
+ + this.dirs['emoticons']
+ + this.emoticonFiles[i]
+ + '" alt="'
+ + this.emoticonCodes[i]
+ + '" title="'
+ + this.emoticonCodes[i]
+ + '"/></a>';
+ }
+ if(this.dom['emoticonsContainer']) {
+ this.updateDOM('emoticonsContainer', this.DOMbuffer);
+ }
+ this.DOMbuffer = "";
+ },
+
+ initColorCodes: function() {
+ if(this.dom['colorCodesContainer']) {
+ this.DOMbuffer = "";
+ for(var i=0; i<this.colorCodes.length; i++) {
+ this.DOMbuffer = this.DOMbuffer
+ + '<a href="javascript:ajaxChat.setFontColor(\''
+ + this.colorCodes[i]
+ + '\');" style="background-color:'
+ + this.colorCodes[i]
+ + ';" title="'
+ + this.colorCodes[i]
+ + '"></a>'
+ + "\n";
+ }
+ this.updateDOM('colorCodesContainer', this.DOMbuffer);
+ this.DOMbuffer = "";
+ }
+ },
+
+
+ startChatUpdate: function() {
+ // Start the chat update and retrieve current user and channel info and set the login channel:
+ var infos = 'userID,userName,userRole,channelID,channelName';
+ if(this.socketServerEnabled) {
+ infos += ',socketRegistrationID';
+ }
+ var params = '&getInfos=' + this.encodeText(infos);
+ if(!isNaN(parseInt(this.loginChannelID))) {
+ params += '&channelID='+this.loginChannelID;
+ } else if(this.loginChannelName !== null) {
+ params += '&channelName='+this.encodeText(this.loginChannelName);
+ }
+ this.updateChat(params);
+ },
+
+ updateChat: function(paramString) {
+ var requestUrl = this.ajaxURL
+ + '&lastID='
+ + this.lastID;
+ if(paramString) {
+ requestUrl += paramString;
+ }
+ this.makeRequest(requestUrl,'GET',null);
+ },
+
+ loadFlashInterface: function() {
+ if(this.dom['flashInterfaceContainer']) {
+ this.updateDOM(
+ 'flashInterfaceContainer',
+ '<object id="ajaxChatFlashInterface" style="position:absolute; left:-100px;" '
+ +'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
+ +'codebase="'
+ + window.location.protocol
+ +'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" '
+ +'height="1" width="1">'
+ +'<param name="flashvars" value="bridgeName=ajaxChat"/>'
+ +'<param name="src" value="'+this.dirs['flash']+'FABridge.swf"/>'
+ +'<embed name="ajaxChatFlashInterface" type="application/x-shockwave-flash" pluginspage="'
+ + window.location.protocol
+ +'//www.macromedia.com/go/getflashplayer" '
+ +'src="'+this.dirs['flash']+'FABridge.swf" height="1" width="1" flashvars="bridgeName=ajaxChat"/>'
+ +'</object>'
+ );
+ FABridge.addInitializationCallback('ajaxChat', this.flashInterfaceLoadCompleteHandler);
+ }
+ },
+
+ flashInterfaceLoadCompleteHandler: function() {
+ ajaxChat.initializeFlashInterface();
+ },
+
+ initializeFlashInterface: function() {
+ if(this.socketServerEnabled) {
+ this.socketTimerRate = (this.inactiveTimeout-1)*60*1000;
+ this.socketConnect();
+ }
+ this.loadSounds();
+ this.initializeCustomFlashInterface();
+ },
+
+ socketConnect: function() {
+ if(!this.socketIsConnected) {
+ try {
+ if(!this.socket && FABridge.ajaxChat) {
+ this.socket = FABridge.ajaxChat.create('flash.net.XMLSocket');
+ this.socket.addEventListener('connect', this.socketConnectHandler);
+ this.socket.addEventListener('close', this.socketCloseHandler);
+ this.socket.addEventListener('data', this.socketDataHandler);
+ this.socket.addEventListener('ioError', this.socketIOErrorHandler);
+ this.socket.addEventListener('securityError', this.socketSecurityErrorHandler);
+ }
+ this.socket.connect(this.socketServerHost, this.socketServerPort);
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ clearTimeout(this.socketReconnectTimer);
+ this.socketReconnectTimer = null;
+ },
+
+ socketConnectHandler: function(event) {
+ ajaxChat.socketIsConnected = true;
+ // setTimeout is needed to avoid calling the flash interface recursively:
+ setTimeout(ajaxChat.socketRegister, 0);
+ },
+
+ socketCloseHandler: function(event) {
+ ajaxChat.socketIsConnected = false;
+ if(ajaxChat.socket) {
+ clearTimeout(ajaxChat.timer);
+ ajaxChat.updateChat(null);
+ }
+ },
+
+ socketDataHandler: function(event) {
+ ajaxChat.socketUpdate(event.getData());
+ },
+
+ socketIOErrorHandler: function(event) {
+ // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages):
+ setTimeout(function() { ajaxChat.addChatBotMessageToChatList('/error SocketIO'); }, 0);
+ setTimeout(ajaxChat.updateChatlistView, 1);
+ },
+
+ socketSecurityErrorHandler: function(event) {
+ // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages):
+ setTimeout(function() { ajaxChat.addChatBotMessageToChatList('/error SocketSecurity'); }, 0);
+ setTimeout(ajaxChat.updateChatlistView, 1);
+ },
+
+ socketRegister: function() {
+ if(this.socket && this.socketIsConnected) {
+ try {
+ this.socket.send(
+ '<register chatID="'
+ +this.socketServerChatID
+ +'" userID="'
+ +this.userID
+ +'" regID="'
+ +this.socketRegistrationID
+ +'"/>'
+ );
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ },
+
+ loadXML: function(str) {
+ if(!arguments.callee.parser) {
+ try {
+ // DOMParser native implementation (Mozilla, Opera):
+ arguments.callee.parser = new DOMParser();
+ } catch(e) {
+ var customDOMParser = function() {};
+ if(navigator.appName === 'Microsoft Internet Explorer') {
+ // IE implementation:
+ customDOMParser.prototype.parseFromString = function(str, contentType) {
+ if(!arguments.callee.XMLDOM) {
+ arguments.callee.XMLDOM = new ActiveXObject('Microsoft.XMLDOM');
+ }
+ arguments.callee.XMLDOM.loadXML(str);
+ return arguments.callee.XMLDOM;
+ };
+ } else {
+ // Safari, Konqueror:
+ customDOMParser.prototype.parseFromString = function(str, contentType) {
+ if(!arguments.callee.httpRequest) {
+ arguments.callee.httpRequest = new XMLHttpRequest();
+ }
+ arguments.callee.httpRequest.open(
+ 'GET',
+ 'data:text/xml;charset=utf-8,'+encodeURIComponent(str),
+ false
+ );
+ arguments.callee.httpRequest.send(null);
+ return arguments.callee.httpRequest.responseXML;
+ };
+ }
+ arguments.callee.parser = new customDOMParser();
+ }
+ }
+ return arguments.callee.parser.parseFromString(str, 'text/xml');
+ },
+
+ socketUpdate: function(data) {
+ var xmlDoc = this.loadXML(data);
+ if(xmlDoc) {
+ this.handleOnlineUsers(xmlDoc.getElementsByTagName('user'));
+ // If the root node has the attribute "mode" set to "1" it is a channel message:
+ if((this.showChannelMessages || xmlDoc.firstChild.getAttribute('mode') !== '1') && !this.channelSwitch) {
+ var channelID = xmlDoc.firstChild.getAttribute('channelID');
+ if(channelID === this.channelID ||
+ parseInt(channelID) === parseInt(this.userID)+this.privateMessageDiff
+ ) {
+ this.handleChatMessages(xmlDoc.getElementsByTagName('message'));
+ }
+ }
+ }
+ },
+
+ setAudioVolume: function(volume) {
+ volume = parseFloat(volume);
+ if(!isNaN(volume)) {
+ if(volume < 0) {
+ volume = 0.0;
+ } else if(volume > 1) {
+ volume = 1.0;
+ }
+ this.settings['audioVolume'] = volume;
+ try {
+ if(!this.soundTransform) {
+ this.soundTransform = FABridge.ajaxChat.create('flash.media.SoundTransform');
+ }
+ this.soundTransform.setVolume(volume);
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ },
+
+ loadSounds: function() {
+ try {
+ this.setAudioVolume(this.settings['audioVolume']);
+ this.sounds = {};
+ var sound,urlRequest;
+ for(var key in this.soundFiles) {
+ sound = FABridge.ajaxChat.create('flash.media.Sound');
+ sound.addEventListener('complete', this.soundLoadCompleteHandler);
+ sound.addEventListener('ioError', this.soundIOErrorHandler);
+ urlRequest = FABridge.ajaxChat.create('flash.net.URLRequest');
+ urlRequest.setUrl(this.dirs['sounds']+this.soundFiles[key]);
+ sound.load(urlRequest);
+ }
+ } catch(e) {
+ alert(e);
+ }
+ },
+
+ soundLoadCompleteHandler: function(event) {
+ var sound = event.getTarget();
+ for(var key in ajaxChat.soundFiles) {
+ // Get the sound key by matching the sound URL with the sound filename:
+ if((new RegExp(ajaxChat.soundFiles[key])).test(sound.getUrl())) {
+ // Add the loaded sound to the sounds list:
+ ajaxChat.sounds[key] = sound;
+ }
+ }
+ },
+
+ soundIOErrorHandler: function(event) {
+ // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages):
+ setTimeout(function() { ajaxChat.addChatBotMessageToChatList('/error SoundIO'); }, 0);
+ setTimeout(ajaxChat.updateChatlistView, 1);
+ },
+
+ soundPlayCompleteHandler: function(event) {
+ // soundChannel event 'soundComplete'
+ },
+
+ playSound: function(soundID) {
+ if(this.sounds && this.sounds[soundID]) {
+ try {
+ // play() parameters are
+ // startTime:Number (default = 0),
+ // loops:int (default = 0) and
+ // sndTransform:SoundTransform (default = null)
+ return this.sounds[soundID].play(0, 0, this.soundTransform);
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ return null;
+ },
+
+ playSoundOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ if(this.settings['audio'] && this.sounds && this.lastID && !this.channelSwitch) {
+ switch(userID) {
+ case this.chatBotID:
+ var messageParts = messageText.split(' ', 1);
+ switch(messageParts[0]) {
+ case '/login':
+ case '/channelEnter':
+ this.playSound(this.settings['soundEnter']);
+ break;
+ case '/logout':
+ case '/channelLeave':
+ case '/kick':
+ this.playSound(this.settings['soundLeave']);
+ break;
+ case '/error':
+ this.playSound(this.settings['soundError']);
+ break;
+ default:
+ this.playSound(this.settings['soundChatBot']);
+ }
+ break;
+ case this.userID:
+ this.playSound(this.settings['soundSend']);
+ break;
+ default:
+ this.playSound(this.settings['soundReceive']);
+ break;
+ }
+ }
+ },
+
+ fillSoundSelection: function(selectionID, selectedSound) {
+ var selection = document.getElementById(selectionID);
+ // Skip the first, empty selection:
+ var i = 1;
+ for(var key in this.soundFiles) {
+ selection.options[i] = new Option(key, key);
+ if(key === selectedSound){
+ selection.options[i].selected = true;
+ }
+ i++;
+ }
+ },
+
+ setStatus: function(newStatus) {
+ // status options are: ok, retrying, waiting
+ if (this.requestStatus !== 'retrying' || newStatus === 'ok') {
+ this.requestStatus = newStatus;
+ }
+
+ var statusIcon = document.getElementById('statusIconContainer');
+
+ if (statusIcon) {
+ switch (this.requestStatus) {
+ case 'ok':
+ this.setClass(statusIcon, 'statusContainerOff');
+ break;
+ case 'waiting':
+ this.setClass(statusIcon, 'statusContainerOn');
+ break;
+ case 'retrying':
+ this.setClass(statusIcon, 'statusContainerAlert');
+ break;
+ }
+ }
+ },
+
+ forceNewRequest: function() {
+ ajaxChat.updateChat(null);
+ ajaxChat.setStatus('retrying');
+ },
+
+ getHttpRequest: function(identifier) {
+ if(!this.httpRequest[identifier]) {
+ if (window.XMLHttpRequest) {
+ this.httpRequest[identifier] = new XMLHttpRequest();
+ if (this.httpRequest[identifier].overrideMimeType) {
+ this.httpRequest[identifier].overrideMimeType('text/xml');
+ }
+ } else if (window.ActiveXObject) {
+ try {
+ this.httpRequest[identifier] = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ this.httpRequest[identifier] = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (e) {
+ }
+ }
+ }
+ }
+ return this.httpRequest[identifier];
+ },
+
+ makeRequest: function(url, method, data) {
+ var identifier;
+ this.setStatus('waiting');
+
+ try {
+ if(data) {
+ // Create up to 50 HTTPRequest objects:
+ if(!arguments.callee.identifier || arguments.callee.identifier > 50) {
+ arguments.callee.identifier = 1;
+ } else {
+ arguments.callee.identifier++;
+ }
+ identifier = arguments.callee.identifier;
+ } else {
+ identifier = 0;
+ }
+ //if the response takes longer than retryTimerDelay to give an OK status, abort the connection and start again.
+ this.retryTimer = setTimeout(ajaxChat.forceNewRequest, ajaxChat.retryTimerDelay);
+
+ this.getHttpRequest(identifier).open(method, url, true);
+ this.getHttpRequest(identifier).onreadystatechange = function() {
+ try {
+ ajaxChat.handleResponse(identifier);
+ } catch(e) {
+ try {
+ clearTimeout(ajaxChat.timer);
+ } catch(e) {
+ //alert(e);
+ }
+ try {
+ if(data) {
+ ajaxChat.addChatBotMessageToChatList('/error ConnectionTimeout');
+ ajaxChat.setStatus('retrying');
+ ajaxChat.updateChatlistView();
+ }
+ } catch(e) {
+ //alert(e);
+ }
+ try {
+ ajaxChat.timer = setTimeout(function() { ajaxChat.updateChat(null); }, ajaxChat.timerRate);
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ };
+ if(method === 'POST') {
+ this.getHttpRequest(identifier).setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ }
+ this.getHttpRequest(identifier).send(data);
+ } catch(e) {
+ clearTimeout(this.timer);
+ if(data) {
+ this.addChatBotMessageToChatList('/error ConnectionTimeout');
+ ajaxChat.setStatus('retrying');
+ this.updateChatlistView();
+ }
+ this.timer = setTimeout(function() { ajaxChat.updateChat(null); }, this.timerRate);
+ }
+ },
+
+ handleResponse: function(identifier) {
+ var xmlDoc;
+ if (this.getHttpRequest(identifier).readyState === 4) {
+ if (this.getHttpRequest(identifier).status === 200) {
+ clearTimeout(ajaxChat.retryTimer);
+ xmlDoc = this.getHttpRequest(identifier).responseXML;
+ ajaxChat.setStatus('ok');
+ } else {
+ // Connection status 0 can be ignored.
+ if (this.getHttpRequest(identifier).status === 0) {
+ this.setStatus('waiting');
+ this.updateChatlistView();
+ return false;
+ } else {
+ this.addChatBotMessageToChatList('/error ConnectionStatus '+this.getHttpRequest(identifier).status);
+ this.setStatus('retrying');
+ this.updateChatlistView();
+ return false;
+ }
+ }
+ }
+ if(!xmlDoc) {
+ return false;
+ }
+ this.handleXML(xmlDoc);
+ return true;
+ },
+
+ handleXML: function(xmlDoc) {
+ this.handleInfoMessages(xmlDoc.getElementsByTagName('info'));
+ this.handleOnlineUsers(xmlDoc.getElementsByTagName('user'));
+ this.handleChatMessages(xmlDoc.getElementsByTagName('message'));
+ this.channelSwitch = null;
+ this.setChatUpdateTimer();
+ },
+
+ setChatUpdateTimer: function() {
+ clearTimeout(this.timer);
+ if(this.chatStarted) {
+ var timeout;
+ if(this.socketIsConnected) {
+ timeout = this.socketTimerRate;
+ } else {
+ timeout = this.timerRate;
+ if(this.socketServerEnabled && !this.socketReconnectTimer) {
+ // If the socket connection fails try to reconnect once in a minute:
+ this.socketReconnectTimer = setTimeout(ajaxChat.socketConnect, 60000);
+ }
+ }
+ this.timer = setTimeout(function() {ajaxChat.updateChat(null);}, timeout);
+ }
+ },
+
+ handleInfoMessages: function(infoNodes) {
+ var infoType, infoData;
+ for(var i=0; i<infoNodes.length; i++) {
+ infoType = infoNodes[i].getAttribute('type');
+ infoData = infoNodes[i].firstChild ? infoNodes[i].firstChild.nodeValue : '';
+ this.handleInfoMessage(infoType, infoData);
+ }
+ },
+
+ handleInfoMessage: function(infoType, infoData) {
+ switch(infoType) {
+ case 'channelSwitch':
+ this.clearChatList();
+ this.clearOnlineUsersList();
+ this.setSelectedChannel(infoData);
+ this.channelName = infoData;
+ this.channelSwitch = true;
+ break;
+ case 'channelName':
+ this.setSelectedChannel(infoData);
+ this.channelName = infoData;
+ break;
+ case 'channelID':
+ this.channelID = infoData;
+ break;
+ case 'userID':
+ this.userID = infoData;
+ break;
+ case 'userName':
+ this.userName = infoData;
+ this.encodedUserName = this.scriptLinkEncode(this.userName);
+ this.userNodeString = null;
+ break;
+ case 'userRole':
+ this.userRole = infoData;
+ break;
+ case 'logout':
+ this.handleLogout(infoData);
+ return;
+ case 'socketRegistrationID':
+ this.socketRegistrationID = infoData;
+ this.socketRegister();
+ default:
+ this.handleCustomInfoMessage(infoType, infoData);
+ }
+ },
+
+ handleOnlineUsers: function(userNodes) {
+ if(userNodes.length) {
+ var index,userID,userName,userRole,i,
+ onlineUsers = [];
+ for(i=0; i<userNodes.length; i++) {
+ userID = userNodes[i].getAttribute('userID');
+ userName = userNodes[i].firstChild ? userNodes[i].firstChild.nodeValue : '';
+ userRole = userNodes[i].getAttribute('userRole');
+ onlineUsers.push(userID);
+ index = this.arraySearch(userID, this.usersList);
+ if(index === false) {
+ this.addUserToOnlineList(
+ userID,
+ userName,
+ userRole
+ );
+ } else if(this.userNamesList[index] !== userName) {
+ this.removeUserFromOnlineList(userID, index);
+ this.addUserToOnlineList(
+ userID,
+ userName,
+ userRole
+ );
+ }
+ }
+ // Clear the offline users from the online users list:
+ for(i=0; i<this.usersList.length; i++) {
+ if(!this.inArray(onlineUsers, this.usersList[i])) {
+ this.removeUserFromOnlineList(this.usersList[i], i);
+ }
+ }
+ this.setOnlineListRowClasses();
+ }
+ },
+
+ handleChatMessages: function(messageNodes) {
+ var userNode,userName,textNode,messageText,i;
+ if(messageNodes.length) {
+ for(i=0; i<messageNodes.length; i++) {
+ this.DOMbuffering = true;
+ userNode = messageNodes[i].getElementsByTagName('username')[0];
+ userName = userNode.firstChild ? userNode.firstChild.nodeValue : '';
+ textNode = messageNodes[i].getElementsByTagName('text')[0];
+ messageText = textNode.firstChild ? textNode.firstChild.nodeValue : '';
+ if (i === (messageNodes.length - 1)) {this.DOMbuffering = false;}
+ this.addMessageToChatList(
+ new Date(messageNodes[i].getAttribute('dateTime')),
+ messageNodes[i].getAttribute('userID'),
+ userName,
+ messageNodes[i].getAttribute('userRole'),
+ messageNodes[i].getAttribute('id'),
+ messageText,
+ messageNodes[i].getAttribute('channelID'),
+ messageNodes[i].getAttribute('ip')
+ );
+ }
+ this.DOMbuffering = false;
+ this.updateChatlistView();
+ this.lastID = messageNodes[messageNodes.length-1].getAttribute('id');
+ }
+ },
+
+ setSelectedChannel: function(channel) {
+ var channelSelected = false,
+ i,option,text;
+ if(this.dom['channelSelection']) {
+ // Replace the entities in the channel name with their character equivalent:
+ channel = this.decodeSpecialChars(channel);
+ for(i=0; i<this.dom['channelSelection'].options.length; i++) {
+ if(this.dom['channelSelection'].options[i].value === channel) {
+ this.dom['channelSelection'].options[i].selected = true;
+ channelSelected = true;
+ break;
+ }
+ }
+ // The given channel is not in the list, add it:
+ if(!channelSelected) {
+ option = document.createElement('option');
+ text = document.createTextNode(channel);
+ option.appendChild(text);
+ option.setAttribute('value', channel);
+ option.setAttribute('selected', 'selected');
+ this.dom['channelSelection'].appendChild(option);
+ }
+ }
+ },
+
+ removeUserFromOnlineList: function(userID, index) {
+ this.usersList.splice(index, 1);
+ this.userNamesList.splice(index, 1);
+ if(this.dom['onlineList']) {
+ this.dom['onlineList'].removeChild(this.getUserNode(userID));
+ }
+ },
+
+ addUserToOnlineList: function(userID, userName, userRole) {
+ this.usersList.push(userID);
+ this.userNamesList.push(userName);
+ if(this.dom['onlineList']) {
+ this.updateDOM(
+ 'onlineList',
+ this.getUserNodeString(userID, userName, userRole),
+ (this.userID === userID)
+ );
+ }
+ },
+
+ getUserNodeString: function(userID, userName, userRole) {
+ var encodedUserName, str;
+ if(this.userNodeString && userID === this.userID) {
+ return this.userNodeString;
+ } else {
+ encodedUserName = this.scriptLinkEncode(userName);
+ str = '<div id="'
+ + this.getUserDocumentID(userID)
+ + '"><a href="javascript:ajaxChat.toggleUserMenu(\''
+ + this.getUserMenuDocumentID(userID)
+ + '\', \''
+ + encodedUserName
+ + '\', '
+ + userID
+ + ');" class="'
+ + this.getRoleClass(userRole)
+ + '" title="'
+ + this.lang['toggleUserMenu'].replace(/%s/, userName)
+ + '">'
+ + userName
+ + '</a>'
+ + '<ul class="userMenu" id="'
+ + this.getUserMenuDocumentID(userID)
+ + '"'
+ + ((userID === this.userID) ?
+ '>'+this.getUserNodeStringItems(encodedUserName, userID, false) :
+ ' style="display:none;">')
+ + '</ul>'
+ +'</div>';
+ if(userID === this.userID) {
+ this.userNodeString = str;
+ }
+ return str;
+ }
+ },
+
+ toggleUserMenu: function(menuID, userName, userID) {
+ // If the menu is empty, fill it with user node menu items before toggling it.
+ var isInline = false;
+ if (menuID.indexOf('ium') >= 0 ) {
+ isInline = true;
+ }
+ if(!document.getElementById(menuID).firstChild) {
+ this.updateDOM(
+ menuID,
+ this.getUserNodeStringItems(
+ this.encodeText(this.addSlashes(this.getScriptLinkValue(userName))),
+ userID,
+ isInline
+ ),
+ false,
+ true
+ )
+ }
+ this.showHide(menuID);
+ this.dom['chatList'].scrollTop = this.dom['chatList'].scrollHeight;
+ },
+
+ getUserNodeStringItems: function(encodedUserName, userID, isInline) {
+ var menu;
+ if(encodedUserName !== this.encodedUserName) {
+ menu = '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/msg '
+ + encodedUserName
+ + ' \');">'
+ + this.lang['userMenuSendPrivateMessage']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/describe '
+ + encodedUserName
+ + ' \');">'
+ + this.lang['userMenuDescribe']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/query '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuOpenPrivateChannel']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/query\');">'
+ + this.lang['userMenuClosePrivateChannel']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/ignore '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuIgnore']
+ + '</a></li>';
+ if (isInline) {
+ menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/invite '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuInvite']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/uninvite '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuUninvite']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/whereis '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuWhereis']
+ + '</a></li>';
+ }
+ if(this.userRole === '2' || this.userRole === '3') {
+ menu += '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/kick '
+ + encodedUserName
+ + ' \');">'
+ + this.lang['userMenuKick']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/whois '
+ + encodedUserName
+ + '\');">'
+ + this.lang['userMenuWhois']
+ + '</a></li>';
+ }
+ } else {
+ menu = '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/quit\');">'
+ + this.lang['userMenuLogout']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/who\');">'
+ + this.lang['userMenuWho']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/ignore\');">'
+ + this.lang['userMenuIgnoreList']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/list\');">'
+ + this.lang['userMenuList']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/action \');">'
+ + this.lang['userMenuAction']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/roll \');">'
+ + this.lang['userMenuRoll']
+ + '</a></li>'
+ + '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/nick \');">'
+ + this.lang['userMenuNick']
+ + '</a></li>';
+ if(this.userRole === '1' || this.userRole === '2' || this.userRole === '3') {
+ menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/join\');">'
+ + this.lang['userMenuEnterPrivateRoom']
+ + '</a></li>';
+ if(this.userRole === '2' || this.userRole === '3') {
+ menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/bans\');">'
+ + this.lang['userMenuBans']
+ + '</a></li>';
+ }
+ }
+ }
+ menu += this.getCustomUserMenuItems(encodedUserName, userID);
+ return menu;
+ },
+
+ setOnlineListRowClasses: function() {
+ if(this.dom['onlineList']) {
+ var node = this.dom['onlineList'].firstChild;
+ var rowEven = false;
+ while(node) {
+ this.setClass(node, (rowEven ? 'rowEven' : 'rowOdd'));
+ node = node.nextSibling;
+ rowEven = !rowEven;
+ }
+ }
+ },
+
+ clearChatList: function() {
+ while(this.dom['chatList'].hasChildNodes()) {
+ this.dom['chatList'].removeChild(this.dom['chatList'].firstChild);
+ }
+ },
+
+ clearOnlineUsersList: function() {
+ this.usersList = [];
+ this.userNamesList = [];
+ if(this.dom['onlineList']) {
+ while(this.dom['onlineList'].hasChildNodes()) {
+ this.dom['onlineList'].removeChild(this.dom['onlineList'].firstChild);
+ }
+ }
+ },
+
+ getEncodedChatBotName: function() {
+ if(typeof arguments.callee.encodedChatBotName === 'undefined') {
+ arguments.callee.encodedChatBotName = this.encodeSpecialChars(this.chatBotName);
+ }
+ return arguments.callee.encodedChatBotName;
+ },
+
+ addChatBotMessageToChatList: function(messageText) {
+ this.addMessageToChatList(
+ new Date(),
+ this.chatBotID,
+ this.getEncodedChatBotName(),
+ 4,
+ null,
+ messageText,
+ null
+ );
+ },
+
+ addMessageToChatList: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ // Prevent adding the same message twice:
+ if(this.getMessageNode(messageID)) {
+ return;
+ }
+ if(!this.onNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) {
+ return;
+ }
+ this.DOMbufferRowClass = this.DOMbufferRowClass === 'rowEven' ? 'rowOdd' : 'rowEven';
+ this.DOMbuffer = this.DOMbuffer +
+ this.getChatListMessageString(
+ dateObject, userID, userName, userRole, messageID, messageText, channelID, ip
+ );
+ if(!this.DOMbuffering){
+ this.updateDOM('chatList', this.DOMbuffer);
+ this.DOMbuffer = "";
+ }
+ },
+
+ getChatListMessageString: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ var rowClass = this.DOMbufferRowClass;
+ var userClass = this.getRoleClass(userRole);
+ var colon;
+ if(messageText.indexOf('/action') === 0 || messageText.indexOf('/me') === 0 || messageText.indexOf('/privaction') === 0) {
+ userClass += ' action';
+ colon = ' ';
+ } else {
+ colon = ': ';
+ }
+ var dateTime = this.settings['dateFormat'] ? '<span class="dateTime">'
+ + this.formatDate(this.settings['dateFormat'], dateObject) + '</span> ' : '';
+ return '<div id="'
+ + this.getMessageDocumentID(messageID)
+ + '" class="'
+ + rowClass
+ + '">'
+ + this.getDeletionLink(messageID, userID, userRole, channelID)
+ + dateTime
+ + '<span class="'
+ + userClass
+ + '"'
+ + this.getChatListUserNameTitle(userID, userName, userRole, ip)
+ + ' dir="'
+ + this.baseDirection
+ + '" onclick="ajaxChat.insertText(this.firstChild.nodeValue);">'
+ + userName
+ + '</span>'
+ + colon
+ + this.replaceText(messageText)
+ + '</div>';
+ },
+
+ getChatListUserNameTitle: function(userID, userName, userRole, ip) {
+ return (ip !== null) ? ' title="IP: ' + ip + '"' : '';
+ },
+
+ getMessageDocumentID: function(messageID) {
+ return ((messageID === null) ? 'ajaxChat_lm_'+(this.localID++) : 'ajaxChat_m_'+messageID);
+ },
+
+ getMessageNode: function(messageID) {
+ return ((messageID === null) ? null : document.getElementById(this.getMessageDocumentID(messageID)));
+ },
+
+ getUserDocumentID: function(userID) {
+ return 'ajaxChat_u_'+userID;
+ },
+
+ getUserNode: function(userID) {
+ return document.getElementById(this.getUserDocumentID(userID));
+ },
+
+ getUserMenuDocumentID: function(userID) {
+ return 'ajaxChat_um_'+userID;
+ },
+
+ getInlineUserMenuDocumentID: function(menuID, index) {
+ return 'ajaxChat_ium_'+menuID+'_'+index;
+ },
+
+ getDeletionLink: function(messageID, userID, userRole, channelID) {
+ if(messageID !== null && this.isAllowedToDeleteMessage(messageID, userID, userRole, channelID)) {
+ if(!arguments.callee.deleteMessage) {
+ arguments.callee.deleteMessage = this.encodeSpecialChars(this.lang['deleteMessage']);
+ }
+ return '<a class="delete" title="'
+ + arguments.callee.deleteMessage
+ + '" href="javascript:ajaxChat.deleteMessage('
+ + messageID
+ + ');"> </a>'; // Adding a space - without any content Opera messes up the chatlist display
+ }
+ return '';
+ },
+
+ isAllowedToDeleteMessage: function(messageID, userID, userRole, channelID) {
+ if((((this.userRole === '1' && this.allowUserMessageDelete && (userID === this.userID ||
+ parseInt(channelID) === parseInt(this.userID)+this.privateMessageDiff ||
+ parseInt(channelID) === parseInt(this.userID)+this.privateChannelDiff)) ||
+ this.userRole === '2') && userRole !== '3' && userRole !== '4') || this.userRole === '3') {
+ return true;
+ }
+ return false;
+ },
+
+ onNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ if(!this.customOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) {
+ return false;
+ }
+ if(this.ignoreMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) {
+ return false;
+ }
+ if(this.parseDeleteMessageCommand(messageText)) {
+ return false;
+ }
+ this.blinkOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip);
+ this.playSoundOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip);
+ return true;
+ },
+
+ parseDeleteMessageCommand: function(messageText) {
+ if(messageText.indexOf('/delete') === 0) {
+ var messageID = messageText.substr(8);
+ var messageNode = this.getMessageNode(messageID);
+ if(messageNode) {
+ var nextSibling = messageNode.nextSibling;
+ try {
+ this.dom['chatList'].removeChild(messageNode);
+ if(nextSibling) {
+ this.updateChatListRowClasses(nextSibling);
+ }
+ } catch(e) {
+ }
+ }
+ return true;
+ }
+ return false;
+ },
+
+ blinkOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ if(this.settings['blink'] && this.lastID && !this.channelSwitch && userID !== this.userID) {
+ clearInterval(this.blinkInterval);
+ this.blinkInterval = setInterval(
+ 'ajaxChat.blinkUpdate(\''+this.addSlashes(this.decodeSpecialChars(userName))+'\')',
+ this.settings['blinkInterval']
+ );
+ }
+ },
+
+ blinkUpdate: function(blinkStr) {
+ if(!this.originalDocumentTitle) {
+ this.originalDocumentTitle = document.title;
+ }
+ if(!arguments.callee.blink) {
+ document.title = '[@ ] '+blinkStr+' - '+this.originalDocumentTitle;
+ arguments.callee.blink = 1;
+ } else if(arguments.callee.blink > this.settings['blinkIntervalNumber']) {
+ clearInterval(this.blinkInterval);
+ document.title = this.originalDocumentTitle;
+ arguments.callee.blink = 0;
+ } else {
+ if(arguments.callee.blink % 2 !== 0) {
+ document.title = '[@ ] '+blinkStr+' - '+this.originalDocumentTitle;
+ } else {
+ document.title = '[ @] '+blinkStr+' - '+this.originalDocumentTitle;
+ }
+ arguments.callee.blink++;
+ }
+ },
+
+ updateChatlistView: function() {
+ if(this.dom['chatList'].childNodes && this.settings['maxMessages']) {
+ while(this.dom['chatList'].childNodes.length > this.settings['maxMessages']) {
+ this.dom['chatList'].removeChild(this.dom['chatList'].firstChild);
+ }
+ }
+
+ if(this.settings['autoScroll']) {
+ this.dom['chatList'].scrollTop = this.dom['chatList'].scrollHeight;
+ }
+ },
+
+ encodeText: function(text) {
+ return encodeURIComponent(text);
+ },
+
+ decodeText: function(text) {
+ return decodeURIComponent(text);
+ },
+
+ utf8Encode: function(plainText) {
+ var utf8Text = '';
+ for(var i=0; i<plainText.length; i++) {
+ var c=plainText.charCodeAt(i);
+ if(c<128) {
+ utf8Text += String.fromCharCode(c);
+ } else if((c>127) && (c<2048)) {
+ utf8Text += String.fromCharCode((c>>6)|192);
+ utf8Text += String.fromCharCode((c&63)|128);
+ } else {
+ utf8Text += String.fromCharCode((c>>12)|224);
+ utf8Text += String.fromCharCode(((c>>6)&63)|128);
+ utf8Text += String.fromCharCode((c&63)|128);
+ }
+ }
+ return utf8Text;
+ },
+
+ utf8Decode: function(utf8Text) {
+ var plainText = '';
+ var c,c2,c3;
+ var i=0;
+ while(i<utf8Text.length) {
+ c = utf8Text.charCodeAt(i);
+ if(c<128) {
+ plainText += String.fromCharCode(c);
+ i++;
+ } else if((c>191) && (c<224)) {
+ c2 = utf8Text.charCodeAt(i+1);
+ plainText += String.fromCharCode(((c&31)<<6) | (c2&63));
+ i+=2;
+ } else {
+ c2 = utf8Text.charCodeAt(i+1);
+ c3 = utf8Text.charCodeAt(i+2);
+ plainText += String.fromCharCode(((c&15)<<12) | ((c2&63)<<6) | (c3&63));
+ i+=3;
+ }
+ }
+ return plainText;
+ },
+
+ encodeSpecialChars: function(text) {
+ return text.replace(
+ /[&<>'"]/g,
+ this.encodeSpecialCharsCallback
+ );
+ },
+
+ encodeSpecialCharsCallback: function(str) {
+ switch(str) {
+ case '&':
+ return '&amp;';
+ case '<':
+ return '&lt;';
+ case '>':
+ return '&gt;';
+ case '\'':
+ // As &apos; is not supported by IE, we use &#39; as replacement for ('):
+ return '&#39;';
+ case '"':
+ return '&quot;';
+ default:
+ return str;
+ }
+ },
+
+ decodeSpecialChars: function(text) {
+ var regExp = new RegExp('(&amp;)|(&lt;)|(&gt;)|(&#39;)|(&quot;)', 'g');
+
+ return text.replace(
+ regExp,
+ this.decodeSpecialCharsCallback
+ );
+ },
+
+ decodeSpecialCharsCallback: function(str) {
+ switch(str) {
+ case '&amp;':
+ return '&';
+ case '&lt;':
+ return '<';
+ case '&gt;':
+ return '>';
+ case '&#39;':
+ return '\'';
+ case '&quot;':
+ return '"';
+ default:
+ return str;
+ }
+ },
+
+ inArray: function(haystack, needle) {
+ var i = haystack.length;
+ while(i--) {
+ if(haystack[i] === needle) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ arraySearch: function(needle, haystack) {
+ var i = haystack.length;
+ while(i--) {
+ if(haystack[i] === needle) {
+ return i;
+ }
+ }
+ return false;
+ },
+
+ stripTags: function(str) {
+ if (!arguments.callee.regExp) {
+ arguments.callee.regExp = new RegExp('<\\/?[^>]+?>', 'g');
+ }
+
+ return str.replace(arguments.callee.regExp, '');
+ },
+
+ stripBBCodeTags: function(str) {
+ if (!arguments.callee.regExp) {
+ arguments.callee.regExp = new RegExp('\\[\\/?[^\\]]+?\\]', 'g');
+ }
+
+ return str.replace(arguments.callee.regExp, '');
+ },
+
+ escapeRegExp: function(text) {
+ if (!arguments.callee.regExp) {
+ var specials = new Array(
+ '^', '$', '*', '+', '?', '.', '|', '/',
+ '(', ')', '[', ']', '{', '}', '\\'
+ );
+ arguments.callee.regExp = new RegExp(
+ '(\\' + specials.join('|\\') + ')', 'g'
+ );
+ }
+ return text.replace(arguments.callee.regExp, '\\$1');
+ },
+
+ addSlashes: function(text) {
+ // Adding slashes in front of apostrophs and backslashes to ensure a valid JavaScript expression:
+ return text.replace(/\\/g, '\\\\').replace(/\'/g, '\\\'');
+ },
+
+ removeSlashes: function(text) {
+ // Removing slashes added by calling addSlashes(text) previously:
+ return text.replace(/\\\\/g, '\\').replace(/\\\'/g, '\'');
+ },
+
+ formatDate: function(format, date) {
+ date = (date == null) ? new date() : date;
+
+ return format
+ .replace(/%Y/g, date.getFullYear())
+ .replace(/%m/g, this.addLeadingZero(date.getMonth()+1))
+ .replace(/%d/g, this.addLeadingZero(date.getDate()))
+ .replace(/%H/g, this.addLeadingZero(date.getHours()))
+ .replace(/%i/g, this.addLeadingZero(date.getMinutes()))
+ .replace(/%s/g, this.addLeadingZero(date.getSeconds()));
+ },
+
+ addLeadingZero: function(number) {
+ number = number.toString();
+ if(number.length < 2) {
+ number = '0'+number;
+ }
+ return number;
+ },
+
+ getUserIDFromUserName: function(userName) {
+ var index = this.arraySearch(userName, this.userNamesList);
+ if(index !== false) {
+ return this.usersList[index];
+ }
+ return null;
+ },
+
+ getUserNameFromUserID: function(userID) {
+ var index = this.arraySearch(userID, this.usersList);
+ if(index !== false) {
+ return this.userNamesList[index];
+ }
+ return null;
+ },
+
+ getRoleClass: function(roleID) {
+ switch(parseInt(roleID)) {
+ case 0:
+ return 'guest';
+ case 1:
+ return 'user';
+ case 2:
+ return 'moderator';
+ case 3:
+ return 'admin';
+ case 4:
+ return 'chatBot';
+ default:
+ return 'default';
+ }
+ },
+
+ handleInputFieldKeyPress: function(event) {
+ if(event.keyCode === 13 && !event.shiftKey) {
+ this.sendMessage();
+ try {
+ event.preventDefault();
+ } catch(e) {
+ event.returnValue = false; // IE
+ }
+ return false;
+ }
+ return true;
+ },
+
+ handleInputFieldKeyUp: function(event) {
+ this.updateMessageLengthCounter();
+ },
+
+ updateMessageLengthCounter: function() {
+ if(this.dom['messageLengthCounter']) {
+ this.updateDOM(
+ 'messageLengthCounter',
+ this.dom['inputField'].value.length + '/' + this.messageTextMaxLength,
+ false,
+ true
+ );
+ }
+ },
+
+ sendMessage: function(text) {
+ text = text ? text : this.dom['inputField'].value;
+ if(!text) {
+ return;
+ }
+ text = this.parseInputMessage(text);
+ if(text) {
+ clearTimeout(this.timer);
+ var message = 'lastID='
+ + this.lastID
+ + '&text='
+ + this.encodeText(text);
+ this.makeRequest(this.ajaxURL,'POST',message);
+ }
+ this.dom['inputField'].value = '';
+ this.dom['inputField'].focus();
+ this.updateMessageLengthCounter();
+ },
+
+ parseInputMessage: function(text) {
+ var textParts;
+ if(text.charAt(0) === '/') {
+ textParts = text.split(' ');
+ switch(textParts[0]) {
+ case '/ignore':
+ text = this.parseIgnoreInputCommand(text, textParts);
+ break;
+ case '/clear':
+ this.clearChatList();
+ return false;
+ break;
+ default:
+ text = this.parseCustomInputCommand(text, textParts);
+ }
+ if(text && this.settings['persistFontColor'] && this.settings['fontColor']) {
+ text = this.assignFontColorToCommandMessage(text, textParts);
+ }
+ } else {
+ text = this.parseCustomInputMessage(text);
+ if(text && this.settings['persistFontColor'] && this.settings['fontColor']) {
+ text = this.assignFontColorToMessage(text);
+ }
+ }
+ return text;
+ },
+
+ assignFontColorToMessage: function(text) {
+ return '[color='+this.settings['fontColor']+']'+text+'[/color]';
+ },
+
+ assignFontColorToCommandMessage: function(text, textParts) {
+ switch(textParts[0]) {
+ case '/msg':
+ case '/describe':
+ if(textParts.length > 2) {
+ return textParts[0]+' '+textParts[1]+' '
+ + '[color='+this.settings['fontColor']+']'
+ + textParts.slice(2).join(' ')
+ + '[/color]';
+ }
+ break;
+ case '/me':
+ case '/action':
+ if(textParts.length > 1) {
+ return textParts[0]+' '
+ + '[color='+this.settings['fontColor']+']'
+ + textParts.slice(1).join(' ')
+ + '[/color]';
+ }
+ break;
+ }
+ return text;
+ },
+
+ parseIgnoreInputCommand: function(text, textParts) {
+ var userName, ignoredUserNames = this.getIgnoredUserNames(), i;
+ if(textParts.length > 1) {
+ userName = this.encodeSpecialChars(textParts[1]);
+ // Prevent adding the chatBot or current user to the list:
+ if(userName === this.userName || userName === this.getEncodedChatBotName()) {
+ // Display the list of ignored users instead:
+ return this.parseIgnoreInputCommand(null, new Array('/ignore'));
+ }
+ if(ignoredUserNames.length > 0) {
+ i = ignoredUserNames.length;
+ while(i--) {
+ if(ignoredUserNames[i] === userName) {
+ ignoredUserNames.splice(i,1);
+ this.addChatBotMessageToChatList('/ignoreRemoved '+userName);
+ this.setIgnoredUserNames(ignoredUserNames);
+ this.updateChatlistView();
+ return null;
+ }
+ }
+ }
+ ignoredUserNames.push(userName);
+ this.addChatBotMessageToChatList('/ignoreAdded '+userName);
+ this.setIgnoredUserNames(ignoredUserNames);
+ } else {
+ if(ignoredUserNames.length === 0) {
+ this.addChatBotMessageToChatList('/ignoreListEmpty -');
+ } else {
+ this.addChatBotMessageToChatList('/ignoreList '+ignoredUserNames.join(' '));
+ }
+ }
+ this.updateChatlistView();
+ return null;
+ },
+
+ getIgnoredUserNames: function() {
+ var ignoredUserNamesString;
+ if(!this.ignoredUserNames) {
+ ignoredUserNamesString = this.getSetting('ignoredUserNames');
+ if(ignoredUserNamesString) {
+ this.ignoredUserNames = ignoredUserNamesString.split(' ');
+ } else {
+ this.ignoredUserNames = [];
+ }
+ }
+ return this.ignoredUserNames;
+ },
+
+ setIgnoredUserNames: function(ignoredUserNames) {
+ this.ignoredUserNames = ignoredUserNames;
+ this.setSetting('ignoredUserNames', ignoredUserNames.join(' '));
+ },
+
+ ignoreMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ var textParts;
+ if(userID === this.chatBotID && messageText.charAt(0) === '/') {
+ textParts = messageText.split(' ');
+ if(textParts.length > 1) {
+ switch(textParts[0]) {
+ case '/invite':
+ case '/uninvite':
+ case '/roll':
+ userName = textParts[1];
+ break;
+ }
+ }
+ }
+ if(this.inArray(this.getIgnoredUserNames(), userName)) {
+ return true;
+ }
+ return false;
+ },
+
+ deleteMessage: function(messageID) {
+ var messageNode = this.getMessageNode(messageID), originalClass, nextSibling;
+ if(messageNode) {
+ originalClass = this.getClass(messageNode);
+ this.setClass(messageNode, originalClass+' deleteSelected');
+ if(confirm(this.lang['deleteMessageConfirm'])) {
+ nextSibling = messageNode.nextSibling;
+ try {
+ this.dom['chatList'].removeChild(messageNode);
+ if(nextSibling) {
+ this.updateChatListRowClasses(nextSibling);
+ }
+ this.updateChat('&delete='+messageID);
+ } catch(e) {
+ this.setClass(messageNode, originalClass);
+ }
+ } else {
+ this.setClass(messageNode, originalClass);
+ }
+ }
+ },
+
+ updateChatListRowClasses: function(node) {
+ var previousNode, rowEven;
+ if(!node) {
+ node = this.dom['chatList'].firstChild;
+ }
+ if(node) {
+ previousNode = node.previousSibling;
+ rowEven = (previousNode && this.getClass(previousNode) === 'rowOdd') ? true : false;
+ while(node) {
+ this.setClass(node, (rowEven ? 'rowEven' : 'rowOdd'));
+ node = node.nextSibling;
+ rowEven = !rowEven;
+ }
+ }
+ },
+
+ getClass: function(node) {
+ if(typeof node.className !== 'undefined') {
+ return node.className; // IE
+ } else {
+ return node.getAttribute('class');
+ }
+ },
+
+ setClass: function(node, className) {
+ if(typeof node.className !== 'undefined') {
+ node.className = className; // IE
+ } else {
+ node.setAttribute('class', className);
+ }
+ },
+
+ scriptLinkEncode: function(text) {
+ return this.encodeText(this.addSlashes(this.decodeSpecialChars(text)));
+ },
+
+ scriptLinkDecode: function(text) {
+ return this.encodeSpecialChars(this.removeSlashes(this.decodeText(text)));
+ },
+
+ getScriptLinkValue: function(value) {
+ // This method returns plainText encoded values from javascript links
+ // The value has to be utf8Decoded for MSIE and Opera:
+ if(typeof arguments.callee.utf8Decode === 'undefined') {
+ switch(navigator.appName) {
+ case 'Microsoft Internet Explorer':
+ case 'Opera':
+ arguments.callee.utf8Decode = true;
+ return this.utf8Decode(value);
+ default:
+ arguments.callee.utf8Decode = false;
+ return value;
+ }
+ } else if(arguments.callee.utf8Decode) {
+ return this.utf8Decode(value);
+ } else {
+ return value;
+ }
+ },
+
+ sendMessageWrapper: function(text) {
+ this.sendMessage(this.getScriptLinkValue(text));
+ },
+
+ insertMessageWrapper: function(text) {
+ this.insertText(this.getScriptLinkValue(text), true);
+ },
+
+ switchChannel: function(channel) {
+ if(!this.chatStarted) {
+ this.clearChatList();
+ this.channelSwitch = true;
+ this.loginChannelID = null;
+ this.loginChannelName = channel;
+ this.requestTeaserContent();
+ return;
+ }
+ clearTimeout(this.timer);
+ var message = 'lastID='
+ + this.lastID
+ + '&channelName='
+ + this.encodeText(channel);
+ this.makeRequest(this.ajaxURL,'POST',message);
+ if(this.dom['inputField'] && this.settings['autoFocus']) {
+ this.dom['inputField'].focus();
+ }
+ },
+
+ logout: function() {
+ clearTimeout(this.timer);
+ var message = 'logout=true';
+ this.makeRequest(this.ajaxURL,'POST',message);
+ },
+
+ handleLogout: function(url) {
+ window.location.href = url;
+ },
+
+ toggleSetting: function(setting, buttonID) {
+ this.setSetting(setting, !this.getSetting(setting));
+ if(buttonID) {
+ this.updateButton(setting, buttonID);
+ }
+ },
+
+ updateButton: function(setting, buttonID) {
+ var node = document.getElementById(buttonID);
+ if(node) {
+ this.setClass(node, (this.getSetting(setting) ? 'button' : 'button off'));
+ }
+ },
+
+ showHide: function(id, styleDisplay, displayInline) {
+ var node = document.getElementById(id);
+ if(node) {
+ if(styleDisplay) {
+ node.style.display = styleDisplay;
+ } else {
+ if(node.style.display === 'none') {
+ node.style.display = (displayInline ? 'inline' : 'block');
+ } else {
+ node.style.display = 'none';
+ }
+ }
+ }
+ },
+
+ setPersistFontColor: function(bool) {
+ this.settings['persistFontColor'] = bool;
+ if(!this.settings['persistFontColor']) {
+ this.settings['fontColor'] = null;
+ if(this.dom['inputField']) {
+ this.dom['inputField'].style.color = '';
+ }
+ }
+ },
+
+ setFontColor: function(color) {
+ if(this.settings['persistFontColor']) {
+ this.settings['fontColor'] = color;
+ if(this.dom['inputField']) {
+ this.dom['inputField'].style.color = color;
+ }
+ if(this.dom['colorCodesContainer']) {
+ this.dom['colorCodesContainer'].style.display = 'none';
+ if(this.dom['inputField']) {
+ this.dom['inputField'].focus();
+ }
+ }
+ } else {
+ this.insert('[color=' + color + ']', '[/color]');
+ }
+ },
+
+ insertText: function(text, clearInputField) {
+ if(clearInputField) {
+ this.dom['inputField'].value = '';
+ }
+ this.insert(text, '');
+ },
+
+ insertBBCode: function(bbCode) {
+ switch(bbCode) {
+ case 'url':
+ var url = prompt(this.lang['urlDialog'], 'http://');
+ if(url)
+ this.insert('[url=' + url + ']', '[/url]');
+ else
+ this.dom['inputField'].focus();
+ break;
+ default:
+ this.insert('[' + bbCode + ']', '[/' + bbCode + ']');
+ }
+ },
+
+ insert: function(startTag, endTag) {
+ this.dom['inputField'].focus();
+ // Internet Explorer:
+ if(typeof document.selection !== 'undefined') {
+ // Insert the tags:
+ var range = document.selection.createRange();
+ var insText = range.text;
+ range.text = startTag + insText + endTag;
+ // Adjust the cursor position:
+ range = document.selection.createRange();
+ if (insText.length === 0) {
+ range.move('character', -endTag.length);
+ } else {
+ range.moveStart('character', startTag.length + insText.length + endTag.length);
+ }
+ range.select();
+ }
+ // Firefox, etc. (Gecko based browsers):
+ else if(typeof this.dom['inputField'].selectionStart !== 'undefined') {
+ // Insert the tags:
+ var start = this.dom['inputField'].selectionStart;
+ var end = this.dom['inputField'].selectionEnd;
+ var insText = this.dom['inputField'].value.substring(start, end);
+ this.dom['inputField'].value = this.dom['inputField'].value.substr(0, start)
+ + startTag
+ + insText
+ + endTag
+ + this.dom['inputField'].value.substr(end);
+ // Adjust the cursor position:
+ var pos;
+ if (insText.length === 0) {
+ pos = start + startTag.length;
+ } else {
+ pos = start + startTag.length + insText.length + endTag.length;
+ }
+ this.dom['inputField'].selectionStart = pos;
+ this.dom['inputField'].selectionEnd = pos;
+ }
+ // Other browsers:
+ else {
+ var pos = this.dom['inputField'].value.length;
+ this.dom['inputField'].value = this.dom['inputField'].value.substr(0, pos)
+ + startTag
+ + endTag
+ + this.dom['inputField'].value.substr(pos);
+ }
+ },
+
+ replaceText: function(text) {
+ try{
+ text = this.replaceLineBreaks(text);
+ if(text.charAt(0) === '/') {
+ text = this.replaceCommands(text);
+ } else {
+ text = this.replaceBBCode(text);
+ text = this.replaceHyperLinks(text);
+ text = this.replaceEmoticons(text);
+ }
+ text = this.breakLongWords(text);
+ text = this.replaceCustomText(text);
+ } catch(e){
+ //alert(e);
+ }
+ return text;
+ },
+
+ replaceCommands: function(text) {
+ try {
+ if(text.charAt(0) !== '/') {
+ return text;
+ }
+ var textParts = text.split(' ');
+ switch(textParts[0]) {
+ case '/login':
+ return this.replaceCommandLogin(textParts);
+ case '/logout':
+ return this.replaceCommandLogout(textParts);
+ case '/channelEnter':
+ return this.replaceCommandChannelEnter(textParts);
+ case '/channelLeave':
+ return this.replaceCommandChannelLeave(textParts);
+ case '/privmsg':
+ return this.replaceCommandPrivMsg(textParts);
+ case '/privmsgto':
+ return this.replaceCommandPrivMsgTo(textParts);
+ case '/privaction':
+ return this.replaceCommandPrivAction(textParts);
+ case '/privactionto':
+ return this.replaceCommandPrivActionTo(textParts);
+ case '/me':
+ case '/action':
+ return this.replaceCommandAction(textParts);
+ case '/invite':
+ return this.replaceCommandInvite(textParts);
+ case '/inviteto':
+ return this.replaceCommandInviteTo(textParts);
+ case '/uninvite':
+ return this.replaceCommandUninvite(textParts);
+ case '/uninviteto':
+ return this.replaceCommandUninviteTo(textParts);
+ case '/queryOpen':
+ return this.replaceCommandQueryOpen(textParts);
+ case '/queryClose':
+ return this.replaceCommandQueryClose(textParts);
+ case '/ignoreAdded':
+ return this.replaceCommandIgnoreAdded(textParts);
+ case '/ignoreRemoved':
+ return this.replaceCommandIgnoreRemoved(textParts);
+ case '/ignoreList':
+ return this.replaceCommandIgnoreList(textParts);
+ case '/ignoreListEmpty':
+ return this.replaceCommandIgnoreListEmpty(textParts);
+ case '/kick':
+ return this.replaceCommandKick(textParts);
+ case '/who':
+ return this.replaceCommandWho(textParts);
+ case '/whoChannel':
+ return this.replaceCommandWhoChannel(textParts);
+ case '/whoEmpty':
+ return this.replaceCommandWhoEmpty(textParts);
+ case '/list':
+ return this.replaceCommandList(textParts);
+ case '/bans':
+ return this.replaceCommandBans(textParts);
+ case '/bansEmpty':
+ return this.replaceCommandBansEmpty(textParts);
+ case '/unban':
+ return this.replaceCommandUnban(textParts);
+ case '/whois':
+ return this.replaceCommandWhois(textParts);
+ case '/whereis':
+ return this.replaceCommandWhereis(textParts);
+ case '/roll':
+ return this.replaceCommandRoll(textParts);
+ case '/nick':
+ return this.replaceCommandNick(textParts);
+ case '/error':
+ return this.replaceCommandError(textParts);
+ default:
+ return this.replaceCustomCommands(text, textParts);
+ }
+ } catch(e) {
+ //alert(e);
+ }
+ return text;
+ },
+
+ replaceCommandLogin: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['login'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandLogout: function(textParts) {
+ var type = '';
+ if(textParts.length === 3)
+ type = textParts[2];
+ return '<span class="chatBotMessage">'
+ + this.lang['logout' + type].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandChannelEnter: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['channelEnter'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandChannelLeave: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['channelLeave'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandPrivMsg: function(textParts) {
+ var privMsgText = textParts.slice(1).join(' ');
+ privMsgText = this.replaceBBCode(privMsgText);
+ privMsgText = this.replaceHyperLinks(privMsgText);
+ privMsgText = this.replaceEmoticons(privMsgText);
+ return '<span class="privmsg">'
+ + this.lang['privmsg']
+ + '</span> '
+ + privMsgText;
+ },
+
+ replaceCommandPrivMsgTo: function(textParts) {
+ var privMsgText = textParts.slice(2).join(' ');
+ privMsgText = this.replaceBBCode(privMsgText);
+ privMsgText = this.replaceHyperLinks(privMsgText);
+ privMsgText = this.replaceEmoticons(privMsgText);
+ return '<span class="privmsg">'
+ + this.lang['privmsgto'].replace(/%s/, textParts[1])
+ + '</span> '
+ + privMsgText;
+ },
+
+ replaceCommandPrivAction: function(textParts) {
+ var privActionText = textParts.slice(1).join(' ');
+ privActionText = this.replaceBBCode(privActionText);
+ privActionText = this.replaceHyperLinks(privActionText);
+ privActionText = this.replaceEmoticons(privActionText);
+ return '<span class="action">'
+ + privActionText
+ + '</span> <span class="privmsg">'
+ + this.lang['privmsg']
+ + '</span> ';
+ },
+
+ replaceCommandPrivActionTo: function(textParts) {
+ var privActionText = textParts.slice(2).join(' ');
+ privActionText = this.replaceBBCode(privActionText);
+ privActionText = this.replaceHyperLinks(privActionText);
+ privActionText = this.replaceEmoticons(privActionText);
+ return '<span class="action">'
+ + privActionText
+ + '</span> <span class="privmsg">'
+ + this.lang['privmsgto'].replace(/%s/, textParts[1])
+ + '</span> ';
+ },
+
+ replaceCommandAction: function(textParts) {
+ var actionText = textParts.slice(1).join(' ');
+ actionText = this.replaceBBCode(actionText);
+ actionText = this.replaceHyperLinks(actionText);
+ actionText = this.replaceEmoticons(actionText);
+ return '<span class="action">'
+ + actionText
+ + '</span>';
+ },
+
+ replaceCommandInvite: function(textParts) {
+ var inviteText = this.lang['invite']
+ .replace(/%s/, textParts[1])
+ .replace(
+ /%s/,
+ '<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
+ + this.scriptLinkEncode(textParts[2])
+ + '\');" title="'
+ + this.lang['joinChannel'].replace(/%s/, textParts[2])
+ + '">'
+ + textParts[2]
+ + '</a>'
+ );
+ return '<span class="chatBotMessage">'
+ + inviteText
+ + '</span>';
+ },
+
+ replaceCommandInviteTo: function(textParts) {
+ var inviteText = this.lang['inviteto']
+ .replace(/%s/, textParts[1])
+ .replace(/%s/, textParts[2]);
+ return '<span class="chatBotMessage">'
+ + inviteText
+ + '</span>';
+ },
+
+ replaceCommandUninvite: function(textParts) {
+ var uninviteText = this.lang['uninvite']
+ .replace(/%s/, textParts[1])
+ .replace(/%s/, textParts[2]);
+ return '<span class="chatBotMessage">'
+ + uninviteText
+ + '</span>';
+ },
+
+ replaceCommandUninviteTo: function(textParts) {
+ var uninviteText = this.lang['uninviteto']
+ .replace(/%s/, textParts[1])
+ .replace(/%s/, textParts[2]);
+ return '<span class="chatBotMessage">'
+ + uninviteText
+ + '</span>';
+ },
+
+ replaceCommandQueryOpen: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['queryOpen'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandQueryClose: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['queryClose'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandIgnoreAdded: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['ignoreAdded'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandIgnoreRemoved: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['ignoreRemoved'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandIgnoreList: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['ignoreList'] + ' '
+ + this.getInlineUserMenu(textParts.slice(1))
+ + '</span>';
+ },
+
+ replaceCommandIgnoreListEmpty: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['ignoreListEmpty']
+ + '</span>';
+ },
+
+ replaceCommandKick: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['logoutKicked'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandWho: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['who'] + ' '
+ + this.getInlineUserMenu(textParts.slice(1))
+ + '</span>';
+ },
+
+ replaceCommandWhoChannel: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['whoChannel'].replace(/%s/, textParts[1]) + ' '
+ + this.getInlineUserMenu(textParts.slice(2))
+ + '</span>';
+ },
+
+ replaceCommandWhoEmpty: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['whoEmpty']
+ + '</span>';
+ },
+
+ replaceCommandList: function(textParts) {
+ var channels = textParts.slice(1);
+ var listChannels = [];
+ var channelName;
+ for(var i=0; i<channels.length; i++) {
+ channelName = (channels[i] === this.channelName) ? '<b>'+channels[i]+'</b>' : channels[i];
+ listChannels.push(
+ '<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
+ + this.scriptLinkEncode(channels[i])
+ + '\');" title="'
+ + this.lang['joinChannel'].replace(/%s/, channels[i])
+ + '">'
+ + channelName
+ + '</a>'
+ );
+ }
+ return '<span class="chatBotMessage">'
+ + this.lang['list'] + ' '
+ + listChannels.join(', ')
+ + '</span>';
+ },
+
+ replaceCommandBans: function(textParts) {
+ var users = textParts.slice(1);
+ var listUsers = [];
+ for(var i=0; i<users.length; i++) {
+ listUsers.push(
+ '<a href="javascript:ajaxChat.sendMessageWrapper(\'/unban '
+ + this.scriptLinkEncode(users[i])
+ + '\');" title="'
+ + this.lang['unbanUser'].replace(/%s/, users[i])
+ + '">'
+ + users[i]
+ + '</a>'
+ );
+ }
+ return '<span class="chatBotMessage">'
+ + this.lang['bans'] + ' '
+ + listUsers.join(', ')
+ + '</span>';
+ },
+
+ replaceCommandBansEmpty: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['bansEmpty']
+ + '</span>';
+ },
+
+ replaceCommandUnban: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['unban'].replace(/%s/, textParts[1])
+ + '</span>';
+ },
+
+ replaceCommandWhois: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['whois'].replace(/%s/, textParts[1]) + ' '
+ + textParts[2]
+ + '</span>';
+ },
+
+ replaceCommandWhereis: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['whereis'].replace(/%s/, textParts[1]).replace(
+ /%s/,
+ '<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
+ + this.scriptLinkEncode(textParts[2])
+ + '\');" title="'
+ + this.lang['joinChannel'].replace(/%s/, textParts[2])
+ + '">'
+ + textParts[2]
+ + '</a>'
+ )
+ + '</span>';
+ },
+
+ replaceCommandRoll: function(textParts) {
+ var rollText = this.lang['roll'].replace(/%s/, textParts[1]);
+ rollText = rollText.replace(/%s/, textParts[2]);
+ rollText = rollText.replace(/%s/, textParts[3]);
+ return '<span class="chatBotMessage">'
+ + rollText
+ + '</span>';
+ },
+
+ replaceCommandNick: function(textParts) {
+ return '<span class="chatBotMessage">'
+ + this.lang['nick'].replace(/%s/, textParts[1]).replace(/%s/, textParts[2])
+ + '</span>';
+ },
+
+ replaceCommandError: function(textParts) {
+ var errorMessage = this.lang['error'+textParts[1]];
+ if(!errorMessage) {
+ errorMessage = 'Error: Unknown.';
+ } else if(textParts.length > 2) {
+ errorMessage = errorMessage.replace(/%s/, textParts.slice(2).join(' '));
+ }
+ return '<span class="chatBotErrorMessage">'
+ + errorMessage
+ + '</span>';
+ },
+
+ getInlineUserMenu: function(users) {
+ var menu = '';
+ for(var i=0; i<users.length; i++) {
+ if(i>0) {
+ menu += ', ';
+ }
+ menu += '<a href="javascript:ajaxChat.toggleUserMenu(\''
+ + this.getInlineUserMenuDocumentID(this.userMenuCounter, i)
+ + '\', \''
+ + this.scriptLinkEncode(users[i])
+ + '\', null);" title="'
+ + this.lang['toggleUserMenu'].replace(/%s/, users[i])
+ + '" dir="'
+ + this.baseDirection
+ + '">'
+ + ((users[i] === this.userName) ? '<b>'+users[i]+'</b>' : users[i])
+ + '</a>'
+ + '<ul class="inlineUserMenu" id="'
+ + this.getInlineUserMenuDocumentID(this.userMenuCounter, i)
+ + '" style="display:none;">'
+ + '</ul>';
+ }
+ this.userMenuCounter++;
+ return menu;
+ },
+
+ containsUnclosedTags: function(str) {
+ var openTags, closeTags,
+ regExpOpenTags = /<[^>\/]+?>/gm,
+ regExpCloseTags = /<\/[^>]+?>/gm;
+
+ openTags = str.match(regExpOpenTags);
+ closeTags = str.match(regExpCloseTags);
+ // Return true if the number of tags doesn't match:
+ if((!openTags && closeTags) ||
+ (openTags && !closeTags) ||
+ (openTags && closeTags && (openTags.length !== closeTags.length))) {
+ return true;
+ }
+ return false;
+ },
+
+ breakLongWords: function(text) {
+ var newText, charCounter, currentChar, withinTag, withinEntity, i;
+
+ if(!this.settings['wordWrap'])
+ return text;
+
+ newText = '';
+ charCounter = 0;
+
+ for(i=0; i<text.length; i++) {
+ currentChar = text.charAt(i);
+
+ // Check if we are within a tag or entity:
+ if(currentChar === '<') {
+ withinTag = true;
+ // Reset the charCounter after newline tags (<br/>):
+ if(i>5 && text.substr(i-5,4) === '<br/')
+ charCounter = 0;
+ } else if(withinTag && i>0 && text.charAt(i-1) === '>') {
+ withinTag = false;
+ // Reset the charCounter after newline tags (<br/>):
+ if(i>4 && text.substr(i-5,4) === '<br/')
+ charCounter = 0;
+ }
+
+ if(!withinTag && currentChar === '&') {
+ withinEntity = true;
+ } else if(withinEntity && i>0 && text.charAt(i-1) === ';') {
+ withinEntity = false;
+ // We only increase the charCounter once for the whole entiy:
+ charCounter++;
+ }
+
+ if(!withinTag && !withinEntity) {
+ // Reset the charCounter if we encounter a word boundary:
+ if(currentChar === ' ' || currentChar === '\n' || currentChar === '\t') {
+ charCounter = 0;
+ } else {
+ // We are not within a tag or entity, increase the charCounter:
+ charCounter++;
+ }
+ if(charCounter > this.settings['maxWordLength']) {
+ // maxWordLength has been reached, break here and reset the charCounter:
+ newText += '&#8203;';
+ charCounter = 0;
+ }
+ }
+ // Add the current char to the text:
+ newText += currentChar;
+ }
+
+ return newText;
+ },
+
+ replaceBBCode: function(text) {
+ if(!this.settings['bbCode']) {
+ // If BBCode is disabled, just strip the text from BBCode tags:
+ return text.replace(/\[(?:\/)?(\w+)(?:=([^<>]*?))?\]/, '');
+ }
+ // Remove the BBCode tags:
+ return text.replace(
+ /\[(\w+)(?:=([^<>]*?))?\](.+?)\[\/\1\]/gm,
+ this.replaceBBCodeCallback
+ );
+ },
+
+ replaceBBCodeCallback: function(str, p1, p2, p3) {
+ // Only replace predefined BBCode tags:
+ if(!ajaxChat.inArray(ajaxChat.bbCodeTags, p1)) {
+ return str;
+ }
+ // Avoid invalid XHTML (unclosed tags):
+ if(ajaxChat.containsUnclosedTags(p3)) {
+ return str;
+ }
+ switch(p1) {
+ case 'color':
+ return ajaxChat.replaceBBCodeColor(p3, p2);
+ case 'url':
+ return ajaxChat.replaceBBCodeUrl(p3, p2);
+ case 'img':
+ return ajaxChat.replaceBBCodeImage(p3);
+ case 'quote':
+ return ajaxChat.replaceBBCodeQuote(p3, p2);
+ case 'code':
+ return ajaxChat.replaceBBCodeCode(p3);
+ case 'u':
+ return ajaxChat.replaceBBCodeUnderline(p3);
+ default:
+ return ajaxChat.replaceCustomBBCode(p1, p2, p3);
+ }
+ },
+
+ replaceBBCodeColor: function(content, attribute) {
+ if(this.settings['bbCodeColors']) {
+ // Only allow predefined color codes:
+ if(!attribute || !this.inArray(ajaxChat.colorCodes, attribute))
+ return content;
+ return '<span style="color:'
+ + attribute + ';">'
+ + this.replaceBBCode(content)
+ + '</span>';
+ }
+ return content;
+ },
+
+ replaceBBCodeUrl: function(content, attribute) {
+ var url, regExpUrl;
+ if(attribute)
+ url = attribute.replace(/\s/gm, this.encodeText(' '));
+ else
+ url = this.stripBBCodeTags(content.replace(/\s/gm, this.encodeText(' ')));
+ regExpUrl = new RegExp(
+ '^(?:(?:http)|(?:https)|(?:ftp)|(?:irc)):\\/\\/',
+ ''
+ );
+ if(!url || !url.match(regExpUrl))
+ return content;
+ return '<a href="'
+ + url
+ + '" onclick="window.open(this.href); return false;">'
+ + this.replaceBBCode(content)
+ + '</a>';
+ },
+
+ replaceBBCodeImage: function(url) {
+ var regExpUrl, maxWidth, maxHeight;
+ if(this.settings['bbCodeImages']) {
+ regExpUrl = new RegExp(
+ this.regExpMediaUrl,
+ ''
+ );
+ if(!url || !url.match(regExpUrl))
+ return url;
+ url = url.replace(/\s/gm, this.encodeText(' '));
+ maxWidth = this.dom['chatList'].offsetWidth-50;
+ maxHeight = this.dom['chatList'].offsetHeight-50;
+ return '<a href="'
+ +url
+ +'" onclick="window.open(this.href); return false;">'
+ +'<img class="bbCodeImage" style="max-width:'
+ +maxWidth
+ +'px; max-height:'
+ +maxHeight
+ +'px;" src="'
+ +url
+ +'" alt="" onload="ajaxChat.updateChatlistView();"/></a>';
+ }
+ return url;
+ },
+
+ replaceBBCodeQuote: function(content, attribute) {
+ if(attribute)
+ return '<span class="quote"><cite>'
+ + this.lang['cite'].replace(/%s/, attribute)
+ + '</cite><q>'
+ + this.replaceBBCode(content)
+ + '</q></span>';
+ return '<span class="quote"><q>'
+ + this.replaceBBCode(content)
+ + '</q></span>';
+ },
+
+ replaceBBCodeCode: function(content) {
+ // Replace vertical tabs and multiple spaces with two non-breaking space characters:
+ return '<code>'
+ + this.replaceBBCode(content.replace(/\t|(?: )/gm, '&#160;&#160;'))
+ + '</code>';
+ },
+
+ replaceBBCodeUnderline: function(content) {
+ return '<span style="text-decoration:underline;">'
+ + this.replaceBBCode(content)
+ + '</span>';
+ },
+
+ replaceHyperLinks: function(text) {
+ var regExp;
+ if(!this.settings['hyperLinks']) {
+ return text;
+ }
+ regExp = new RegExp(
+ '(^|\\s|>)((?:(?:http)|(?:https)|(?:ftp)|(?:irc)):\\/\\/[^\\s<>]+)(<\\/a>)?',
+ 'gm'
+ );
+ return text.replace(
+ regExp,
+ // Specifying an anonymous function as second parameter:
+ function(str, p1, p2, p3) {
+ // Do not replace URL's inside URL's:
+ if(p3) {
+ return str;
+ }
+ return p1
+ + '<a href="'
+ + p2
+ + '" onclick="window.open(this.href); return false;">'
+ + p2
+ + '</a>';
+ }
+ );
+ },
+
+ replaceLineBreaks: function(text) {
+ var regExp = new RegExp('\\n', 'g');
+
+ if(!this.settings['lineBreaks']) {
+ return text.replace(regExp, ' ');
+ } else {
+ return text.replace(regExp, '<br/>');
+ }
+ },
+
+ replaceEmoticons: function(text) {
+ if(!this.settings['emoticons']) {
+ return text;
+ }
+ if(!arguments.callee.regExp) {
+ var regExpStr = '^(.*)(';
+ for(var i=0; i<this.emoticonCodes.length; i++) {
+ if(i!==0)
+ regExpStr += '|';
+ regExpStr += '(?:' + this.escapeRegExp(this.emoticonCodes[i]) + ')';
+ }
+ regExpStr += ')(.*)$';
+ arguments.callee.regExp = new RegExp(regExpStr, 'gm');
+ }
+ return text.replace(
+ arguments.callee.regExp,
+ this.replaceEmoticonsCallback
+ );
+ },
+
+ replaceEmoticonsCallback: function(str, p1, p2, p3) {
+ if (!arguments.callee.regExp) {
+ arguments.callee.regExp = new RegExp('(="[^"]*$)|(&[^;]*$)', '');
+ }
+ // Avoid replacing emoticons in tag attributes or XHTML entities:
+ if(p1.match(arguments.callee.regExp)) {
+ return str;
+ }
+ if(p2) {
+ var index = ajaxChat.arraySearch(p2, ajaxChat.emoticonCodes);
+ return ajaxChat.replaceEmoticons(p1)
+ + '<img src="'
+ + ajaxChat.dirs['emoticons']
+ + ajaxChat.emoticonFiles[index]
+ + '" alt="'
+ + p2
+ + '" />'
+ + ajaxChat.replaceEmoticons(p3);
+ }
+ return str;
+ },
+
+ getActiveStyle: function() {
+ var cookie = this.readCookie(this.sessionName + '_style');
+ var style = cookie ? cookie : this.getPreferredStyleSheet();
+ return style;
+ },
+
+ initStyle: function() {
+ this.styleInitiated = true;
+ this.setActiveStyleSheet(this.getActiveStyle());
+ },
+
+ persistStyle: function() {
+ if(this.styleInitiated) {
+ this.createCookie(this.sessionName + '_style', this.getActiveStyleSheet(), this.cookieExpiration);
+ }
+ },
+
+ setSelectedStyle: function() {
+ if(this.dom['styleSelection']) {
+ var style = this.getActiveStyle();
+ var styleOptions = this.dom['styleSelection'].getElementsByTagName('option');
+ for(var i=0; i<styleOptions.length; i++) {
+ if(styleOptions[i].value == style) {
+ styleOptions[i].selected = true;
+ break;
+ }
+ }
+ }
+ },
+
+ getSelectedStyle: function() {
+ var styleOptions = this.dom['styleSelection'].getElementsByTagName('option');
+ if(this.dom['styleSelection'].selectedIndex === -1) {
+ return styleOptions[0].value;
+ } else {
+ return styleOptions[this.dom['styleSelection'].selectedIndex].value;
+ }
+ },
+
+ setActiveStyleSheet: function(title) {
+ var i, a, main, titleFound = false;
+ for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
+ if(a.getAttribute('rel').indexOf('style') !== -1 && a.getAttribute('title')) {
+ a.disabled = true;
+ if(a.getAttribute('title') === title) {
+ a.disabled = false;
+ titleFound = true;
+ }
+ }
+ }
+ if(!titleFound && title !== null) {
+ this.setActiveStyleSheet(this.getPreferredStyleSheet());
+ }
+ },
+
+ getActiveStyleSheet: function() {
+ var i, a;
+ for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
+ if(a.getAttribute('rel').indexOf('style') != -1 && a.getAttribute('title') && !a.disabled) {
+ return a.getAttribute('title');
+ }
+ }
+ return null;
+ },
+
+ getPreferredStyleSheet: function() {
+ var i,a;
+ for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
+ if(a.getAttribute('rel').indexOf('style') !== -1
+ && a.getAttribute('rel').indexOf('alt') === -1
+ && a.getAttribute('title')
+ ) {
+ return a.getAttribute('title');
+ }
+ }
+ return null;
+ },
+
+ switchLanguage: function(langCode) {
+ window.location.search = '?lang='+langCode;
+ },
+
+ createCookie: function(name,value,days) {
+ var expires = '';
+ if(days) {
+ var date = new Date();
+ date.setTime(date.getTime()+(days*24*60*60*1000));
+ expires = '; expires='+date.toGMTString();
+ }
+ var path = '; path='+this.cookiePath;
+ var domain = this.cookieDomain ? '; domain='+this.cookieDomain : '';
+ var secure = this.cookieSecure ? '; secure' : '';
+ document.cookie = name+'='+encodeURIComponent(value)+expires+path+domain+secure;
+ },
+
+ readCookie: function(name) {
+ if(!document.cookie)
+ return null;
+ var nameEQ = name + '=';
+ var ca = document.cookie.split(';');
+ for(var i=0; i<ca.length; i++) {
+ var c = ca[i];
+ while(c.charAt(0) === ' ') {
+ c = c.substring(1, c.length);
+ }
+ if(c.indexOf(nameEQ) === 0) {
+ return decodeURIComponent(c.substring(nameEQ.length, c.length));
+ }
+ }
+ return null;
+ },
+
+ isCookieEnabled: function() {
+ this.createCookie(this.sessionName + '_cookie_test', true, 1);
+ var cookie = this.readCookie(this.sessionName + '_cookie_test');
+ if(cookie) {
+ // Unset the test cookie:
+ this.createCookie(this.sessionName + '_cookie_test', true, -1);
+ // Cookie test successfull, return true:
+ return true;
+ }
+ return false;
+ },
+
+ finalize: function() {
+ if(typeof this.finalizeFunction === 'function') {
+ this.finalizeFunction();
+ }
+ // Ensure the socket connection is closed on unload:
+ if(this.socket) {
+ try {
+ this.socket.close();
+ this.socket = null;
+ } catch(e) {
+ //alert(e);
+ }
+ }
+ this.persistSettings();
+ this.persistStyle();
+ this.customFinalize();
+ },
+
+ // Override to perform custom actions on flash initialization:
+ initializeCustomFlashInterface: function() {
+ },
+
+ // Override to handle custom info messages
+ handleCustomInfoMessage: function(infoType, infoData) {
+ },
+
+ // Override to add custom initialization code
+ // This method is called on page load
+ customInitialize: function() {
+ },
+
+ // Override to add custom finalization code
+ // This method is called on page unload
+ customFinalize: function() {
+ },
+
+ // Override to add custom user menu items:
+ // Return a string with list items ( <li>menuItem</li> )
+ // encodedUserName contains the userName ready to be used for javascript links
+ // userID is only available for the online users menu - not for the inline user menu
+ // use (encodedUserName == this.encodedUserName) to check for the current user
+ getCustomUserMenuItems: function(encodedUserName, userID) {
+ return '';
+ },
+
+ // Override to parse custom input messages:
+ // Return replaced text
+ // text contains the whole message
+ parseCustomInputMessage: function(text) {
+ return text;
+ },
+
+ // Override to parse custom input commands:
+ // Return parsed text
+ // text contains the whole message, textParts the message split up as words array
+ parseCustomInputCommand: function(text, textParts) {
+ return text;
+ },
+
+ // Override to replace custom text:
+ // Return replaced text
+ // text contains the whole message
+ replaceCustomText: function(text) {
+ return text;
+ },
+
+ // Override to replace custom commands:
+ // Return replaced text for custom commands
+ // text contains the whole message, textParts the message split up as words array
+ replaceCustomCommands: function(text, textParts) {
+ return text;
+ },
+
+ // Override to replace custom BBCodes:
+ // Return replaced text and call replaceBBCode recursively for the content text
+ // tag contains the BBCode tag, attribute the BBCode attribute and content the content text
+ // This method is only called for BBCode tags which are in the bbCodeTags list
+ replaceCustomBBCode: function(tag, attribute, content) {
+ return '<' + tag + '>' + this.replaceBBCode(content) + '</' + tag + '>';
+ },
+
+ // Override to perform custom actions on new messages:
+ // Return true if message is to be added to the chatList, else false
+ customOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) {
+ return true;
+ }
+
+}; \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/config.js b/library/ajaxchat/chat/js/config.js
new file mode 100644
index 000000000..a4d3c3f75
--- /dev/null
+++ b/library/ajaxchat/chat/js/config.js
@@ -0,0 +1,261 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat config parameters:
+var ajaxChatConfig = {
+
+ // The channelID of the channel to enter on login (the loginChannelName is used if set to null):
+ loginChannelID: null,
+ // The channelName of the channel to enter on login (the default channel is used if set to null):
+ loginChannelName: null,
+
+ // The time in ms between update calls to retrieve new chat messages:
+ timerRate: 2000,
+
+ // The URL to retrieve the XML chat messages (must at least contain one parameter):
+ ajaxURL: './?ajax=true',
+ // The base URL of the chat directory, used to retrieve media files (images, sound files, etc.):
+ baseURL: './',
+
+ // A regular expression for allowed source URL's for media content (e.g. images displayed inline);
+ regExpMediaUrl: '^((http)|(https)):\\/\\/',
+
+ // If set to false the chat update is delayed until the event defined in ajaxChat.setStartChatHandler():
+ startChatOnLoad: true,
+
+ // Defines the IDs of DOM nodes accessed by the chat:
+ domIDs: {
+ // The ID of the chat messages list:
+ chatList: 'chatList',
+ // The ID of the online users list:
+ onlineList: 'onlineList',
+ // The ID of the message text input field:
+ inputField: 'inputField',
+ // The ID of the message text length counter:
+ messageLengthCounter: 'messageLengthCounter',
+ // The ID of the channel selection:
+ channelSelection: 'channelSelection',
+ // The ID of the style selection:
+ styleSelection: 'styleSelection',
+ // The ID of the emoticons container:
+ emoticonsContainer: 'emoticonsContainer',
+ // The ID of the color codes container:
+ colorCodesContainer: 'colorCodesContainer',
+ // The ID of the flash interface container:
+ flashInterfaceContainer: 'flashInterfaceContainer'
+ },
+
+ // Defines the settings which can be modified by users:
+ settings: {
+ // Defines if BBCode tags are replaced with the associated HTML code tags:
+ bbCode: true,
+ // Defines if image BBCode is replaced with the associated image HTML code:
+ bbCodeImages: true,
+ // Defines if color BBCode is replaced with the associated color HTML code:
+ bbCodeColors: true,
+ // Defines if hyperlinks are made clickable:
+ hyperLinks: true,
+ // Defines if line breaks are enabled:
+ lineBreaks: true,
+ // Defines if emoticon codes are replaced with their associated images:
+ emoticons: true,
+
+ // Defines if the focus is automatically set to the input field on chat load or channel switch:
+ autoFocus: true,
+ // Defines if the chat list scrolls automatically to display the latest messages:
+ autoScroll: true,
+ // The maximum count of messages displayed in the chat list (will be ignored if set to 0):
+ maxMessages: 0,
+
+ // Defines if long words are wrapped to avoid vertical scrolling:
+ wordWrap: true,
+ // Defines the maximum length before a word gets wrapped:
+ maxWordLength: 32,
+
+ // Defines the format of the date and time displayed for each chat message:
+ dateFormat: '(%H:%i:%s)',
+
+ // Defines if font colors persist without the need to assign them to each message:
+ persistFontColor: false,
+ // The default font color, uses the page default font color if set to null:
+ fontColor: null,
+
+ // Defines if sounds are played:
+ audio: true,
+ // Defines the sound volume (0.0 = mute, 1.0 = max):
+ audioVolume: 1.0,
+
+ // Defines the sound that is played when normal messages are reveived:
+ soundReceive: 'sound_1',
+ // Defines the sound that is played on sending normal messages:
+ soundSend: 'sound_2',
+ // Defines the sound that is played on channel enter or login:
+ soundEnter: 'sound_3',
+ // Defines the sound that is played on channel leave or logout:
+ soundLeave: 'sound_4',
+ // Defines the sound that is played on chatBot messages:
+ soundChatBot: 'sound_5',
+ // Defines the sound that is played on error messages:
+ soundError: 'sound_6',
+
+ // Defines if the document title blinks on new messages:
+ blink: true,
+ // Defines the blink interval in ms:
+ blinkInterval: 500,
+ // Defines the number of blink intervals:
+ blinkIntervalNumber: 10
+ },
+
+ // Defines a list of settings which are not to be stored in a session cookie:
+ nonPersistentSettings: [],
+
+ // Defines the list of allowed BBCodes:
+ bbCodeTags:[
+ 'b',
+ 'i',
+ 'u',
+ 'quote',
+ 'code',
+ 'color',
+ 'url',
+ 'img'
+ ],
+
+ // Defines the list of allowed color codes:
+ colorCodes: [
+ 'gray',
+ 'silver',
+ 'white',
+ 'yellow',
+ 'orange',
+ 'red',
+ 'fuchsia',
+ 'purple',
+ 'navy',
+ 'blue',
+ 'aqua',
+ 'teal',
+ 'green',
+ 'lime',
+ 'olive',
+ 'maroon',
+ 'black'
+ ],
+
+ // Defines the list of allowed emoticon codes:
+ emoticonCodes: [
+ ':)',
+ ':(',
+ ';)',
+ ':P',
+ ':D',
+ ':|',
+ ':O',
+ ':?',
+ '8)',
+ '8o',
+ 'B)',
+ ':-)',
+ ':-(',
+ ':-*',
+ 'O:-D',
+ '>:-D',
+ ':o)',
+ ':idea:',
+ ':important:',
+ ':help:',
+ ':error:',
+ ':warning:',
+ ':favorite:'
+ ],
+
+ // Defines the list of emoticon files associated with the emoticon codes:
+ emoticonFiles: [
+ 'smile.png',
+ 'sad.png',
+ 'wink.png',
+ 'razz.png',
+ 'grin.png',
+ 'plain.png',
+ 'surprise.png',
+ 'confused.png',
+ 'glasses.png',
+ 'eek.png',
+ 'cool.png',
+ 'smile-big.png',
+ 'crying.png',
+ 'kiss.png',
+ 'angel.png',
+ 'devilish.png',
+ 'monkey.png',
+ 'idea.png',
+ 'important.png',
+ 'help.png',
+ 'error.png',
+ 'warning.png',
+ 'favorite.png'
+ ],
+
+ // Defines the available sounds loaded on chat start:
+ soundFiles: {
+ sound_1: 'sound_1.mp3',
+ sound_2: 'sound_2.mp3',
+ sound_3: 'sound_3.mp3',
+ sound_4: 'sound_4.mp3',
+ sound_5: 'sound_5.mp3',
+ sound_6: 'sound_6.mp3'
+ },
+
+
+ // Once users have been logged in, the following values are overridden by those in config.php.
+ // You should set these to be the same as the ones in config.php to avoid confusion.
+
+ // Session identification, used for style and setting cookies:
+ sessionName: 'ajax_chat',
+
+ // The time in days until the style and setting cookies expire:
+ cookieExpiration: 365,
+ // The path of the cookies, '/' allows to read the cookies from all directories:
+ cookiePath: '/',
+ // The domain of the cookies, defaults to the hostname of the server if set to null:
+ cookieDomain: null,
+ // If enabled, cookies must be sent over secure (SSL/TLS encrypted) connections:
+ cookieSecure: null,
+
+ // The name of the chat bot:
+ chatBotName: 'ChatBot',
+ // The userID of the chat bot:
+ chatBotID: 2147483647,
+
+ // Allow/Disallow registered users to delete their own messages:
+ allowUserMessageDelete: true,
+
+ // Minutes until a user is declared inactive (last status update) - the minimum is 2 minutes:
+ inactiveTimeout: 2,
+
+ // UserID plus this value are private channels (this is also the max userID and max channelID):
+ privateChannelDiff: 500000000,
+ // UserID plus this value are used for private messages:
+ privateMessageDiff: 1000000000,
+
+ // Defines if login/logout and channel enter/leave are displayed:
+ showChannelMessages: true,
+
+ // Max messageText length:
+ messageTextMaxLength: 1040,
+
+ // Defines if the socket server is enabled:
+ socketServerEnabled: false,
+ // Defines the hostname of the socket server used to connect from client side:
+ socketServerHost: 'localhost',
+ // Defines the port of the socket server:
+ socketServerPort: 1935,
+ // This ID can be used to distinguish between different chat installations using the same socket server:
+ socketServerChatID: 0
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/custom.js b/library/ajaxchat/chat/js/custom.js
new file mode 100644
index 000000000..6d801534e
--- /dev/null
+++ b/library/ajaxchat/chat/js/custom.js
@@ -0,0 +1,16 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Overriding client side functionality:
+
+/*
+// Example - Overriding the replaceCustomCommands method:
+ajaxChat.replaceCustomCommands = function(text, textParts) {
+ return text;
+}
+ */ \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/index.html b/library/ajaxchat/chat/js/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/js/index.html
diff --git a/library/ajaxchat/chat/js/lang/ar.js b/library/ajaxchat/chat/js/lang/ar.js
new file mode 100644
index 000000000..7fd18db10
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ar.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author pepotiger (www.dd4bb.com)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s دخول.',
+ logout: '%s خروج.',
+ logoutTimeout: '%s تم تسجيل الخروج (Timeout).',
+ logoutIP: '%s تم تسجيل الخروج (Invalid IP address).',
+ logoutKicked: '%s تم تسجيل الخروج (Kicked).',
+ channelEnter: '%s دخول المحطة.',
+ channelLeave: '%s خروج.',
+ privmsg: '(رسالة خاصة)',
+ privmsgto: '(رسالة خاصة الى %s)',
+ invite: '%s يدعوك الى %s.',
+ inviteto: 'دعوتك لـ %s للإنضمام الى %s تم ارسالها.',
+ uninvite: '%s الغاء دعوتك من %s.',
+ uninviteto: 'الغاء الدعوة من %s للـ %s تم ارسالها.',
+ queryOpen: 'تم فتح نافذة خاصة مع %s.',
+ queryClose: 'النافذة الخاصة مع %s تم غلقها.',
+ ignoreAdded: 'اضيف %s الى قائمة التجاهل.',
+ ignoreRemoved: 'حذف %s من قائمة التجاهل.',
+ ignoreList: 'اعضاء متجاهلين:',
+ ignoreListEmpty: 'لا يوجد اعضاء تم تجاهلهم.',
+ who: 'المستخدمين المتواجدين:',
+ whoChannel: 'Online Users in channel %s:',
+ whoEmpty: 'لا يوجد اعضاء بهذه المحطة.',
+ list: 'المحطات المتوفرة:',
+ bans: 'اعضاء محجوبين:',
+ bansEmpty: 'لا يوجد اعضاء محجوبين.',
+ unban: 'حظر العضو %s تم الغائه.',
+ whois: 'الأى بى للعضو %s:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s rolls %s and gets %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Change username',
+ userMenuEnterPrivateRoom: 'Enter private room',
+ userMenuSendPrivateMessage: 'Send private message',
+ userMenuDescribe: 'Send private action',
+ userMenuOpenPrivateChannel: 'Open private channel',
+ userMenuClosePrivateChannel: 'Close private channel',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'List ignored users',
+ userMenuWhereis: 'Display channel',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'List banned users',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'الإنضمام للمحطة %s',
+ cite: '%s كتب:',
+ urlDialog: 'من فضلك ادخل الرابط (URL) لعنوان الأنترنت:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'الكوكييز مطلوبة لهذا الشات.',
+ errorUserNameNotFound: 'خطأ: العضو %s لم يتم العثور عليه.',
+ errorMissingText: 'خطأ: نص الرسالة مفقود.',
+ errorMissingUserName: 'خطأ: اسم المستخدم مفقود.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'خطأ: اسم المحطة مفقود.',
+ errorInvalidChannelName: 'خطأ: اسم المحطة غير صحيح: %s',
+ errorPrivateMessageNotAllowed: 'خطأ: غير مسموح بالرسائل الخاصة.',
+ errorInviteNotAllowed: 'خطأ: غير مسموح بدعوة الأخرين.',
+ errorUninviteNotAllowed: 'خطأ: غير مسموح بإلغاء دعوات الأخرين.',
+ errorNoOpenQuery: 'خطأ: لم يتم فتح اى نوافذ خاصة.',
+ errorKickNotAllowed: 'خطأ: غير مسموح لك بطرد احد %s.',
+ errorCommandNotAllowed: 'خطأ: غير مسموح بالأمر: %s',
+ errorUnknownCommand: 'خطأ: امر غير معروف: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'خطأ: وقت الأتصال استنفذ. من فضلك حاول مرة اخرى.',
+ errorConnectionStatus: 'خطأ: حالة الأتصال: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/bg.js b/library/ajaxchat/chat/js/lang/bg.js
new file mode 100644
index 000000000..c1e1886ad
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/bg.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Borislav Manolov
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s влезе в чата.',
+ logout: '%s излезе от чата.',
+ logoutTimeout: '%s излезе автоматично от чата (Изтичане на времето).',
+ logoutIP: '%s излезе автоматично от чата (Грешен айпи адрес).',
+ logoutKicked: '%s излезе автоматично от чата (Изритване).',
+ channelEnter: '%s влезе в канала.',
+ channelLeave: '%s напусна канала.',
+ privmsg: '(прошепва)',
+ privmsgto: '(прошепва на %s)',
+ invite: '%s ви кани да се присъедините към %s.',
+ inviteto: 'Поканата ви към %s да се присъедини към канала %s беше изпратена.',
+ uninvite: '%s отмени поканата ви за канала %s.',
+ uninviteto: 'Отмяната на поканата ви към %s за канала %s беше изпратена.',
+ queryOpen: 'Отворен е личен канал за %s.',
+ queryClose: 'Затворен е личен канал за %s.',
+ ignoreAdded: '%s беше добавен към списъка с пренебрегнатите.',
+ ignoreRemoved: '%s беше изваден от списъка с пренебрегнатите.',
+ ignoreList: 'Пренебрегнати потребители:',
+ ignoreListEmpty: 'Няма пренебрегнати потребители.',
+ who: 'Потребители на линия:',
+ whoChannel: 'Потребители на линия в канала %s:',
+ whoEmpty: 'В дадения канал няма потребители на линия.',
+ list: 'Налични канали:',
+ bans: 'Изгонени потребители:',
+ bansEmpty: 'Няма изгонени потребители.',
+ unban: 'Изгонването на потребителя %s е отменено.',
+ whois: 'Потребител %s — айпи адрес:',
+ whereis: 'Потребителят %s е в канала %s.',
+ roll: '%s хвърли %s и получи %s.',
+ nick: '%s вече се казва %s.',
+ toggleUserMenu: 'Показване/скриване на потребителското меню за %s',
+ userMenuLogout: 'Изход',
+ userMenuWho: 'Потребители на линия',
+ userMenuList: 'Налични канали',
+ userMenuAction: 'Описване на действие',
+ userMenuRoll: 'Хвърляне на зар',
+ userMenuNick: 'Смяна на името',
+ userMenuEnterPrivateRoom: 'Влизане в личната стая',
+ userMenuSendPrivateMessage: 'Изпращане на лично съобщение',
+ userMenuDescribe: 'Изпращане на лично действие',
+ userMenuOpenPrivateChannel: 'Отваряне на личен канал',
+ userMenuClosePrivateChannel: 'Затваряне на личен канал',
+ userMenuInvite: 'Покана',
+ userMenuUninvite: 'Отмяна на покана',
+ userMenuIgnore: 'Пренебрегване/Приемане',
+ userMenuIgnoreList: 'Пренебрегнати потребители',
+ userMenuWhereis: 'Преглед на канал',
+ userMenuKick: 'Изритване/Изгонване',
+ userMenuBans: 'Изгонени потребители',
+ userMenuWhois: 'Преглед на айпи адреса',
+ unbanUser: 'Отмяна на изгонването на %s',
+ joinChannel: 'Присъединяване към канала %s',
+ cite: '%s каза:',
+ urlDialog: 'Моля, въведете адреса (URL) на страницата:',
+ deleteMessage: 'Изтриване на съобщението',
+ deleteMessageConfirm: 'Наистина ли желаете да изтриете съобщението?',
+ errorCookiesRequired: 'За чата се изискват бисквитки (cookies).',
+ errorUserNameNotFound: 'Грешка: Не е намерен потребител %s.',
+ errorMissingText: 'Грешка: Липсва текст на съобщението.',
+ errorMissingUserName: 'Грешка: Липсва потребителско име.',
+ errorInvalidUserName: 'Грешка: Невалидно потребителско име.',
+ errorUserNameInUse: 'Грешка: Това потребителско име вече се използва.',
+ errorMissingChannelName: 'Грешка: Липсва име на канал.',
+ errorInvalidChannelName: 'Грешка: Невалидно име на канал: %s',
+ errorPrivateMessageNotAllowed: 'Грешка: Личните съобщения не са позволени.',
+ errorInviteNotAllowed: 'Грешка: Не ви е позволено да каните потребители в този канал.',
+ errorUninviteNotAllowed: 'Грешка: Не ви е позволено да отменяте покани в този канал.',
+ errorNoOpenQuery: 'Грешка: Не е отворен личен канал.',
+ errorKickNotAllowed: 'Грешка: Не ви е позволено да изритвате %s.',
+ errorCommandNotAllowed: 'Грешка: Командата не е позволена: %s',
+ errorUnknownCommand: 'Грешка: Непозната команда: %s',
+ errorMaxMessageRate: 'Грешка: Превишихте допустимия брой съобщения в минута.',
+ errorConnectionTimeout: 'Грешка: Изтичане на времето за връзка. Моля, опитайте отново!',
+ errorConnectionStatus: 'Грешка: Състояние на връзката: %s',
+ errorSoundIO: 'Грешка: Неуспешно зареждане на звуковия файл (Входно-изходна грешка при Флаш).',
+ errorSocketIO: 'Грешка: Неуспешна връзка към сокетния сървър (Входно-изходна грешка при Флаш).',
+ errorSocketSecurity: 'Грешка: Неуспешна връзка към сокетния сървър (Грешка в сигурността при Флаш).',
+ errorDOMSyntax: 'Грешка: Неправилен синтаксис при DOM (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/ca.js b/library/ajaxchat/chat/js/lang/ca.js
new file mode 100644
index 000000000..83eab4df5
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ca.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Manu Quintans
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+ login: '%s ha entrat al xat.',
+ logout: '%s ha sortit del xat.',
+ logoutTimeout: '%s s\'ha desconnectat (Temps d\'espera esgotat).',
+ logoutIP: '%s s\'ha desconnectat (Adreça IP no vàlida).',
+ logoutKicked: '%s s\'ha desconnectat (Patejat).',
+ channelEnter: '%s entra al canal.',
+ channelLeave: '%s se\'n va del canal.',
+ privmsg: '(xiuxiueigs)',
+ privmsgto: '(xiuxiueigs a %s)',
+ invite: '%s et convida a unir-te a %s.',
+ inviteto: 'El teu convit a %s per a unir-se a %s ha estat enviat.',
+ uninvite: '%s no et convida a %s.',
+ uninviteto: 'El teu no convit a %s per al canal %s ha estat enviat',
+ queryOpen: 'Canal privat obert %s.',
+ queryClose: 'Canal privat tancat %s tancat',
+ ignoreAdded: 'Agregat %s a la llista de usuaris ignorats.',
+ ignoreRemoved: 'Eliminant %s de la llista de usuaris ignorats.',
+ ignoreList: 'Usuaris ignorats',
+ ignoreListEmpty: 'Llista d\'usuaris no ignorats.',
+ who: 'Usuaris connectats:',
+ whoChannel: 'Usuaris en línia al canal %s:',
+ whoEmpty: 'No hi ha usuaris connectats ara.',
+ list: 'Canals disponibles:',
+ bans: 'Usuaris Bannejats:',
+ bansEmpty: 'No s\'han registrat usuaris bannejats.',
+ unban: 'Ban de l\'usuari %s revocat.',
+ whois: 'Usuari %s - Adreça IP:',
+ whereis: 'L\'usuari %s és al canal %s.',
+ roll: '%s tirà els daus %s i aconsegueix %s.',
+ nick: '%s es fa dir ara %s.',
+ toggleUserMenu: 'Tanca menu de l\'usuari per a %s',
+ userMenuLogout: 'Tancar sessió',
+ userMenuWho: 'Llista d\'usuaris en línia',
+ userMenuList: 'Llista de canals disponibles',
+ userMenuAction: 'Descriure una acció',
+ userMenuRoll: 'Tirar daus',
+ userMenuNick: 'Canviar el nom de l\'usuari',
+ userMenuEnterPrivateRoom: 'Entrar en un lloc privat',
+ userMenuSendPrivateMessage: 'Enviar un missatge privat',
+ userMenuDescribe: 'Enviar una acció privada',
+ userMenuOpenPrivateChannel: 'Obrir un canal privat',
+ userMenuClosePrivateChannel: 'Tancar un canal privat',
+ userMenuInvite: 'Convidar',
+ userMenuUninvite: 'Desconvidar',
+ userMenuIgnore: 'Ignorar/Acceptar',
+ userMenuIgnoreList: 'Llista d\'usuaris ignorats',
+ userMenuWhereis: 'Visualitzar el canal',
+ userMenuKick: 'Pateig/Banneig',
+ userMenuBans: 'Llista d\'usuaris banejats',
+ userMenuWhois: 'Mostrar IP',
+ unbanUser: 'Cancel·lar banejament de usuari %s',
+ joinChannel: 'Unir-se al canal %s',
+ cite: '%s va dir:',
+ urlDialog: 'Si us plau, introdueix la adreça (URL) de la pàgina web:',
+ deleteMessage: 'Esborra aquest missatge',
+ deleteMessageConfirm: 'Realment vols esborrar el missatge seleccionat?',
+ errorCookiesRequired: 'Les galetes són necessaries per aquest xat .',
+ errorUserNameNotFound: 'Error: usuari %s no s\'ha trobat.',
+ errorMissingText: 'Error: Missatge perdut.',
+ errorMissingUserName: 'Error: Usuari no trobat.',
+ errorInvalidUserName: 'Error: Nom d\'usuari no vàlid.',
+ errorUserNameInUse: 'Error: El nom d\'usuari ja està en ús.',
+ errorMissingChannelName: 'Error: No es troba el canal.',
+ errorInvalidChannelName: 'Error: nombre del canal invàlid: %s',
+ errorPrivateMessageNotAllowed: 'Error: Els missatges privats no t\'estan permesos.',
+ errorInviteNotAllowed: 'Error: No t\'està permés convidar a ningú a aquest canal.',
+ errorUninviteNotAllowed: 'Error: No t\'està permés desconvidar ningú d\'aquest canal.',
+ errorNoOpenQuery: 'Error: Cap canal privat obert.',
+ errorKickNotAllowed: 'Error: No t\'està permés expulsar a ningú %s.',
+ errorCommandNotAllowed: 'Error: Ordre desconeguda: %s',
+ errorUnknownCommand: 'Error: Ordre desconeguda: %s',
+ errorMaxMessageRate: 'Error: has excedit el màxim nombre de missatges per minut.',
+ errorConnectionTimeout: 'Error: Temps d\'espera de la connexió expirat. Reintenta-ho de nou.',
+ errorConnectionStatus: 'Error: Estat de la connexió: %s',
+ errorSoundIO: 'Error: No ha estat possible carregar el so (Flash IO Error).',
+ errorSocketIO: 'Error: La connexió al servidor ha fallat (Flash IO Error).',
+ errorSocketSecurity: 'Error: La connexió al servidor ha fallat (Flash Security Error).',
+ errorDOMSyntax: 'Error: Sintaxi DOM invàlida (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/cy.js b/library/ajaxchat/chat/js/lang/cy.js
new file mode 100644
index 000000000..fd63aea95
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/cy.js
@@ -0,0 +1,93 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ * @translation Alan Davies, ardavies@tiscali.co.uk
+ * @language: Welsh (Cymraeg)
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: 'Mae %s wedi mewngofnodi.',
+ logout: 'Allgofnododd %s.',
+ logoutTimeout: 'Allgofnodwyd %s (Terfyn amser).',
+ logoutIP: 'Allgofnodwyd %s (Cyfeiriad IP annilys).',
+ logoutKicked: 'Allgofnodwyd %s (Cic).',
+ channelEnter: 'Mae %s wedi ymuno \'r sianel.',
+ channelLeave: 'Mae %s wedi gadael y sianel.',
+ privmsg: '(sibrwd)',
+ privmsgto: '(sibrwd i %s)',
+ invite: 'Mae %s yn eich gwahodd i ymuno %s.',
+ inviteto: 'Mae eich gwahoddiad i %s i ymuno sianel %s wedi\'i anfon.',
+ uninvite: 'Mae %s yn tynnu\'r gwahoddiad i sianel %s yn l.',
+ uninviteto: 'Mae\'r neges yn tynnu\'r gwahoddiad i sianel %s yn l wedi\'i hanfon.',
+ queryOpen: 'Agorwyd sianel breifat i %s.',
+ queryClose: 'Ceuwyd sianel breifat i %s.',
+ ignoreAdded: 'Ychwanegwyd %s i\'r anwybyddion.',
+ ignoreRemoved: 'Tynnwyd %s bant o\'r anwybyddion.',
+ ignoreList: 'Anwybyddion:',
+ ignoreListEmpty: 'Dim anwybyddion wedi\'u rhestru.',
+ who: 'Defnyddwyr Ar-lein:',
+ whoChannel: 'Defnyddwyr Ar-lein ar sianel %s:',
+ whoEmpty: 'Dim defnyddwyr ar-lein ar y sianel hon.',
+ list: 'Sianeli ar gael:',
+ bans: 'Gwaharddogion:',
+ bansEmpty: 'Dim gwaharddogion wedi\'u rhestru.',
+ unban: 'Diddymwyd gwaharddiad %s.',
+ whois: 'Defnyddiwr %s - cyfeiriad IP:',
+ whereis: 'Mae defnyddiwr %s yn y sianel %s.',
+ roll: 'Mae %s yn rholio %s a chael %s.',
+ nick: 'Enw %s nawr yw %s.',
+ toggleUserMenu: 'Togl dewislen defnyddiwr ar gyfer %s',
+ userMenuLogout: 'Allgofnodi',
+ userMenuWho: 'Rhestr ddefnyddwyr ar-lein',
+ userMenuList: 'Rhestr sianeli ar gael',
+ userMenuAction: 'Disgrifio gweithred',
+ userMenuRoll: 'Rholio dis',
+ userMenuNick: 'Newid enw',
+ userMenuEnterPrivateRoom: 'Myned i mewn i ystafell breifat',
+ userMenuSendPrivateMessage: 'Anfon neges breifat',
+ userMenuDescribe: 'Anfon gweithred breifat',
+ userMenuOpenPrivateChannel: 'Agor sianel breifat',
+ userMenuClosePrivateChannel: 'Cau sianel breifat',
+ userMenuInvite: 'Gwahodd',
+ userMenuUninvite: 'Tynnu gwahoddiad',
+ userMenuIgnore: 'Anwybyddu/Derbyn',
+ userMenuIgnoreList: 'Rhestr anwybyddion',
+ userMenuWhereis: 'Dangos sianel',
+ userMenuKick: 'Cic/Gwahardd',
+ userMenuBans: 'Rhestr waharddogion',
+ userMenuWhois: 'Dangos IP',
+ unbanUser: 'Diddynu gwaharddiad %s',
+ joinChannel: 'Ymuno sianel %s',
+ cite: 'Dywedodd %s:',
+ urlDialog: 'Rhowch gyfeiriad (URL) y wefan:',
+ deleteMessage: 'Dilwch y neges hon',
+ deleteMessageConfirm: 'Ydych wir am ddileu\'r neges hon?',
+ errorCookiesRequired: 'Mae nagen cwcis ar gyfer y sgwrs hon.',
+ errorUserNameNotFound: 'Gwall: Heb ffeindio %s.',
+ errorMissingText: 'Gwall: testun neges ar goll.',
+ errorMissingUserName: 'Gwall: Enw ar goll.',
+ errorInvalidUserName: 'Gwall: Enw annilys.',
+ errorUserNameInUse: 'Gwall: Enw\'n bodoli eisoes.',
+ errorMissingChannelName: 'Gwall: Enw sianel ar goll.',
+ errorInvalidChannelName: 'Gwall: Enw sianel annilys: %s',
+ errorPrivateMessageNotAllowed: 'Gwall: Ni chaniateir negesuon preifat.',
+ errorInviteNotAllowed: 'Gwall: Nid oes hawl gwahodd rhywun i\'r sianel hon.',
+ errorUninviteNotAllowed: 'Gwall: Nid oes hawl tynnu gwahaoddiad yn l o\'r sianel hon.',
+ errorNoOpenQuery: 'Gwall: Dim sianel breifat ar agor.',
+ errorKickNotAllowed: 'Gwall: Nid oes hawl cicio %s.',
+ errorCommandNotAllowed: 'Gwall: Nid oes hawl defnyddio\'r gorchymyn: %s',
+ errorUnknownCommand: 'Gwall: Gorchymyn anhysbys: %s',
+ errorMaxMessageRate: 'Gwall: Rydych wedi myn dros y nifer o negeseuon sydd hawl gennych anfon pob munud.',
+ errorConnectionTimeout: 'Gwall: Terfyn amser cysylltiad. Ceisiwch eto.',
+ errorConnectionStatus: 'Gwall: Statws cysylltiad: %s',
+ errorSoundIO: 'Gwall: Methu llwytho ffeil sain (Gwall Flash IO).',
+ errorSocketIO: 'Gwall: Cysylltiad i\'r gweinyddwr soced wedi methu (Gwall Flash IO).',
+ errorSocketSecurity: 'Gwall: Cysylltiad i\'r gweinyddwr soced wedi methu (Gwall Diogelwch Flash).',
+ errorDOMSyntax: 'Gwall: Cystrawen DOM Annilys (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/cz.js b/library/ajaxchat/chat/js/lang/cz.js
new file mode 100644
index 000000000..4a0a7b8b2
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/cz.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s se přihlásil.',
+ logout: '%s se odhlásil.',
+ logoutTimeout: '%s byl odhlášen (překročen timeout).',
+ logoutIP: '%s byl odhlášen (neplatná IP adresa).',
+ logoutKicked: '%s byl vyhozen.',
+ channelEnter: '%s vstoupil do místnosti.',
+ channelLeave: '%s odešel z místnosti.',
+ privmsg: '(šeptá)',
+ privmsgto: '(šeptá %s)',
+ invite: '%s tě zve do místnosti %s.',
+ inviteto: 'Tvoje pozvání %s do místnosti %s bylo odesláno.',
+ uninvite: '%s odmítl pozvání do pokoje %s.',
+ uninviteto: 'Tvoje pozvání %s do pokoje %s bylo odmítnuto.',
+ queryOpen: 'Soukromý rozhovor s %s byl započat.',
+ queryClose: 'Soukromý rozhovor s %s byl ukončen.',
+ ignoreAdded: '%s byl přidán do seznamu ignorovaných.',
+ ignoreRemoved: '%s byl odebrán ze seznamu ignorovaných.',
+ ignoreList: 'Seznam ignorovaných:',
+ ignoreListEmpty: 'Seznam je prázdný...',
+ who: 'Přihlášení uživatelé:',
+ whoChannel: 'Uživatelé, přihlášení v místnosti %s:',
+ whoEmpty: 'Tady nikdo není...',
+ list: 'Dostupné místnosti:',
+ bans: 'Vyhození uživatelé:',
+ bansEmpty: 'Seznam je prázdný...',
+ unban: 'Uživatel %s byl omilostněn.',
+ whois: 'Uživatel %s - IP adresa:',
+ whereis: 'Uživatel %s je v místnosti %s.',
+ roll: '%s hodil %s a vyhrává %s.',
+ nick: '%s se nyní jmenuje %s.',
+ toggleUserMenu: 'Vyvolej/zhasni uživatelskou nabídku pro %s',
+ userMenuLogout: 'Odhlásit',
+ userMenuWho: 'Seznam přihlášených uživatelů',
+ userMenuList: 'Seznam místností',
+ userMenuAction: 'Co právě dělám',
+ userMenuRoll: 'Hodit kostkou',
+ userMenuNick: 'Změnit jméno uživatele',
+ userMenuEnterPrivateRoom: 'Vstoupit do soukromé místnosti',
+ userMenuSendPrivateMessage: 'Poslat soukromou zprávu',
+ userMenuDescribe: 'Co právě dělám (soukromě)',
+ userMenuOpenPrivateChannel: 'Zahájit soukromý rozhovor',
+ userMenuClosePrivateChannel: 'Ukončit soukromý rozhovor',
+ userMenuInvite: 'Pozvat',
+ userMenuUninvite: 'Odmítnout pozvání',
+ userMenuIgnore: 'Ignorovat/Přijmout',
+ userMenuIgnoreList: 'Seznam ignorovaných uživatelů',
+ userMenuWhereis: 'Zobrazit místnost',
+ userMenuKick: 'Vyhodit/Zablokovat',
+ userMenuBans: 'Seznam vyhozených uživatelů',
+ userMenuWhois: 'Zobrazit IP adresu',
+ unbanUser: 'Omilostnit uživatele %s',
+ joinChannel: 'Vstoupit do místnosti %s',
+ cite: '%s prohlásil:',
+ urlDialog: 'Zadej, prosím adresu (URL) stránky:',
+ deleteMessage: 'Vymazat zprávu',
+ deleteMessageConfirm: 'Opravdu vymazat tuto zprávu ?',
+ errorCookiesRequired: 'Pro tento chat je nutno povolit Cookies.',
+ errorUserNameNotFound: 'Chyba: Uživatel %s nebyl nalezen.',
+ errorMissingText: 'Chyba: Schází text zprávy.',
+ errorMissingUserName: 'Chyba: Schází jméno uživatele.',
+ errorInvalidUserName: 'Chyba: Neplatné jméno uživatele.',
+ errorUserNameInUse: 'Chyba: Jméno uživatele už je používáno.',
+ errorMissingChannelName: 'Chyba: Schází název místnosti.',
+ errorInvalidChannelName: 'Chyba: Neplatný název místnosti: %s',
+ errorPrivateMessageNotAllowed: 'Chyba: Soukromé zprávy nejsou povoleny.',
+ errorInviteNotAllowed: 'Chyba: Nejsi oprávněn zvát do této místnosti.',
+ errorUninviteNotAllowed: 'Chyba: Nejsi oprávněn odmítat pozvání z této místnosti.',
+ errorNoOpenQuery: 'Chyba: Nebyl zahájen žádný soukromý rozhovor.',
+ errorKickNotAllowed: 'Chyba: Nemáš právo vyhodit %s.',
+ errorCommandNotAllowed: 'Chyba: Tento příkaz není povolen: %s',
+ errorUnknownCommand: 'Chyba: Neznámý příkaz: %s',
+ errorMaxMessageRate: 'Chyba: Překročil jsi maximální počet zpráv za minutu.',
+ errorConnectionTimeout: 'Chyba: Čas připojení vypršel. Připoj se znovu.',
+ errorConnectionStatus: 'Chyba: Stav připojení: %s',
+ errorSoundIO: 'Chyba: Nepodařilo se přehrát zvukový soubor (Flash IO Error).',
+ errorSocketIO: 'Chyba: Nepodařilo se připojení k serveru (Flash IO Error).',
+ errorSocketSecurity: 'Chyba: Připojení k serveru selhalo (Flash Security Error).',
+ errorDOMSyntax: 'Chyba: Neplatná syntaxe DOM (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/da.js b/library/ajaxchat/chat/js/lang/da.js
new file mode 100644
index 000000000..c6e537aad
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/da.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s Logger dig ind.',
+ logout: '%s Logger dig ud.',
+ logoutTimeout: '%s Er logget ud (Timeout).',
+ logoutIP: '%s er logget ud (ugyldig IP addresse).',
+ logoutKicked: '%s er logget ud (Kicked).',
+ channelEnter: '%s kom ind i kanalen.',
+ channelLeave: '%s forlod kanalen.',
+ privmsg: '(hvisker)',
+ privmsgto: '(hvisker til %s)',
+ invite: '%s inviterede dig til at joine %s.',
+ inviteto: 'Din invitation %s til at joine kanal %s er blevet sendt.',
+ uninvite: '%s Du er nu ikke længere inviteret til %s.',
+ uninviteto: 'Anullere invitation for %s på kanal %s.',
+ queryOpen: 'Privat kanal åben for %s.',
+ queryClose: 'Privat kanal for %s lukket.',
+ ignoreAdded: 'Tilføjede %s til ignorerings listen.',
+ ignoreRemoved: 'fjernede %s fra ignorerings listen.',
+ ignoreList: 'Ignorerede brugere:',
+ ignoreListEmpty: 'Ingen ignorerede brugere.',
+ who: 'Online brugere:',
+ whoChannel: 'Online brugere på kanal %s:',
+ whoEmpty: 'ingen online brugere på den angivne kanal.',
+ list: 'Tilgængelige kanaler:',
+ bans: 'Banlyste brugere:',
+ bansEmpty: 'Ingen banlyste brugere på listen.',
+ unban: 'Banlysning af %s ophævet.',
+ whois: 'bruger %s - IP addresse:',
+ whereis: 'brugeren %s er på kanal %s.',
+ roll: '%s Kastede terninger %s og fik %s.',
+ nick: '%s Er nu kendt som %s.',
+ toggleUserMenu: 'skift bruger menu for %s',
+ userMenuLogout: 'Log ud',
+ userMenuWho: 'Vis online brugere',
+ userMenuList: 'Vis tilgængelige kanaler',
+ userMenuAction: 'Beskrivende handling',
+ userMenuRoll: 'Kast terninger',
+ userMenuNick: 'Skift brugernavn',
+ userMenuEnterPrivateRoom: 'Gå ind i privat rum.',
+ userMenuSendPrivateMessage: 'Send privat besked',
+ userMenuDescribe: 'Send privat handling',
+ userMenuOpenPrivateChannel: 'Åben privat kanal',
+ userMenuClosePrivateChannel: 'Luk privat kanal',
+ userMenuInvite: 'Inviter',
+ userMenuUninvite: 'Anuller invitation',
+ userMenuIgnore: 'Ignorer/Accepter',
+ userMenuIgnoreList: 'Vis ignorerede brugere',
+ userMenuWhereis: 'vis kanal',
+ userMenuKick: 'Spark ud/Banlys',
+ userMenuBans: 'Vis banlyste brugere',
+ userMenuWhois: 'Vis IP adresse',
+ unbanUser: 'Fjernede banlysning af brugere %s',
+ joinChannel: 'Deltag i en kanal %s',
+ cite: '%s sagde:',
+ urlDialog: 'Venligst indsæt adressen (URL) for den pågældende hjemmeside:',
+ deleteMessage: 'Fjern denne chat besked',
+ deleteMessageConfirm: 'Vil du virkelig fjerne denne besked?',
+ errorCookiesRequired: 'Cookies er nødvændige for denne chat',
+ errorUserNameNotFound: 'FEJL: bruger %s ikke fundet.',
+ errorMissingText: 'FEJL: Manglende besked.',
+ errorMissingUserName: 'FEJL: Manglende brugernavn.',
+ errorInvalidUserName: 'FEJL: Ugyldigt brugernavn.',
+ errorUserNameInUse: 'FEJL: Brugernavnet er allerede i brug.',
+ errorMissingChannelName: 'FEJL: Manglende kanal navn.',
+ errorInvalidChannelName: 'FEJL: Ugyldigt kanal navn: %s',
+ errorPrivateMessageNotAllowed: 'FEJL: Privat beskeder er ikke tilladt.',
+ errorInviteNotAllowed: 'FEJL: Du har ikke tilstrækkelige rettigheder til at invitere til denne kanal.',
+ errorUninviteNotAllowed: 'FEJL: Du har ikke tilstrækkelige rettigheder til at anullere invitationer for denne kanal.',
+ errorNoOpenQuery: 'FEJL: Ingen privat kanal åben.',
+ errorKickNotAllowed: 'FEJL: Du har ikke tilstrækkelige rettigheder til at sparke. %s.',
+ errorCommandNotAllowed: 'FEJL: Kommando ikke tillad: %s',
+ errorUnknownCommand: 'FEJL: Ukendt kommando: %s',
+ errorMaxMessageRate: 'FEJL: Du har overskredet max antal beskeder per minut.',
+ errorConnectionTimeout: 'FEJL: Forbindelses timeout. Prøv venligst igen.',
+ errorConnectionStatus: 'FEJL: Status for forbindelse. %s',
+ errorSoundIO: 'FEJL: Kunne ikke indlæse lydfil (Flash IO Fejl).',
+ errorSocketIO: 'FEJL: Connection to socket server failed (Flash IO fejl).',
+ errorSocketSecurity: 'FEJL: forbindelse til til socket server fejlede (Flash sikkerheds fejl).',
+ errorDOMSyntax: 'FEJL: Ugyldig DOM Syntaks(DOM ID: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/de.js b/library/ajaxchat/chat/js/lang/de.js
new file mode 100644
index 000000000..b46b3f323
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/de.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s betritt den Chat.',
+ logout: '%s verlässt den Chat.',
+ logoutTimeout: '%s wurde ausgeloggt (Timeout).',
+ logoutIP: '%s wurde ausgeloggt (Ungültige IP-Adresse).',
+ logoutKicked: '%s wurde ausgeloggt (Ausschluss).',
+ channelEnter: '%s betritt den Raum.',
+ channelLeave: '%s verlässt den Raum.',
+ privmsg: '(flüstert)',
+ privmsgto: '(flüstert zu %s)',
+ invite: '%s lädt dich ein den Raum %s zu betreten.',
+ inviteto: 'Deine Einladung an %s den Raum %s zu betreten wurde versendet.',
+ uninvite: '%s hat dich wieder ausgeladen den Raum %s zu betreten.',
+ uninviteto: 'Deine Ausladung an %s den Raum %s zu betreten wurde versendet.',
+ queryOpen: 'Privater Kanal zu %s geöffnet.',
+ queryClose: 'Privater Kanal zu %s geschlossen.',
+ ignoreAdded: '%s wurde auf die Ignorier-Liste gesetzt.',
+ ignoreRemoved: '%s wurde von der Ignorier-Liste entfernt.',
+ ignoreList: 'Ignorierte Benutzer:',
+ ignoreListEmpty: 'Keine Benutzer werden ignoriert.',
+ who: 'Benutzer online:',
+ whoChannel: 'Benutzer online im Raum %s:',
+ whoEmpty: 'Keine Benutzer online im angegebenen Kanal.',
+ list: 'Verfügbare Räume:',
+ bans: 'Ausgeschlossene Nutzer:',
+ bansEmpty: 'Keine ausgeschlossenen Nutzer vorhanden.',
+ unban: 'Ausschluss des Benutzers %s aufgehoben.',
+ whois: 'Benutzer %s - IP-Adresse:',
+ whereis: 'Benutzer %s ist im Raum %s.',
+ roll: '%s würfelt %s und erhält %s.',
+ nick: '%s heißt jetzt %s.',
+ toggleUserMenu: 'Benutzer-Menü für %s anzeigen/ausblenden',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'Online Benutzer auflisten',
+ userMenuList: 'Verfügbare Räume auflisten',
+ userMenuAction: 'Aktion beschreiben',
+ userMenuRoll: 'Würfeln',
+ userMenuNick: 'Benutzernamen ändern',
+ userMenuEnterPrivateRoom: 'Privaten Raum betreten',
+ userMenuSendPrivateMessage: 'Private Nachricht schicken',
+ userMenuDescribe: 'Private Aktion schicken',
+ userMenuOpenPrivateChannel: 'Privaten Kanal öffnen',
+ userMenuClosePrivateChannel: 'Privaten Kanal schließen',
+ userMenuInvite: 'Einladen',
+ userMenuUninvite: 'Ausladen',
+ userMenuIgnore: 'Ignorieren / Akzeptieren',
+ userMenuIgnoreList: 'Ignorierte Benutzer auflisten',
+ userMenuWhereis: 'Raum anzeigen',
+ userMenuKick: 'Ausschließen / Verbannen',
+ userMenuBans: 'Ausgeschlossene Benutzer auflisten',
+ userMenuWhois: 'IP anzeigen',
+ unbanUser: 'Ausschluss von %s aufheben',
+ joinChannel: 'Raum %s betreten',
+ cite: '%s sagte:',
+ urlDialog: 'Bitte die Adresse (URL) der Webseite eingeben:',
+ deleteMessage: 'Diese Chat-Nachricht löschen',
+ deleteMessageConfirm: 'Die ausgewählte Chat-Nachricht wirklich löschen?',
+ errorCookiesRequired: 'Cookies werden für diesen Chat benötigt.',
+ errorUserNameNotFound: 'Fehler: Benutzer %s wurde nicht gefunden.',
+ errorMissingText: 'Fehler: Nachrichtentext fehlt.',
+ errorMissingUserName: 'Fehler: Benutzername fehlt.',
+ errorInvalidUserName: 'Fehler: Ungültiger Benutzername.',
+ errorUserNameInUse: 'Fehler: Benutzername schon vergeben.',
+ errorMissingChannelName: 'Fehler: Raumname fehlt.',
+ errorInvalidChannelName: 'Fehler: Ungültiger Raumname: %s',
+ errorPrivateMessageNotAllowed: 'Fehler: Private Nachrichten sind nicht erlaubt.',
+ errorInviteNotAllowed: 'Fehler: Du kannst niemanden zu diesem Raum Einladen.',
+ errorUninviteNotAllowed: 'Fehler: Du kannst niemanden von diesem Raum Ausladen.',
+ errorNoOpenQuery: 'Fehler: Kein privater Kanal offen.',
+ errorKickNotAllowed: 'Fehler: Du kannst %s nicht ausschließen.',
+ errorCommandNotAllowed: 'Fehler: Befehl nicht erlaubt: %s',
+ errorUnknownCommand: 'Fehler: Unbekannter Befehl: %s',
+ errorMaxMessageRate: 'Fehler: Du hast die maximale Anzahl an Nachrichten pro Minute überschritten.',
+ errorConnectionTimeout: 'Fehler: Verbindungsabbruch. Bitte erneut versuchen.',
+ errorConnectionStatus: 'Fehler: Verbindungsstatus: %s',
+ errorSoundIO: 'Fehler: Laden einer Sound-Datei fehlgeschlagen (Flash IO Error).',
+ errorSocketIO: 'Fehler: Verbindung zum Socket Server fehlgeschlagen (Flash IO Error).',
+ errorSocketSecurity: 'Fehler: Verbindung zum Socket Server fehlgeschlagen (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/el.js b/library/ajaxchat/chat/js/lang/el.js
new file mode 100644
index 000000000..2864c3a76
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/el.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author panas
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s μπήκε στο Chat.',
+ logout: '%s βγήκε από το Chat.',
+ logoutTimeout: '%s βγήκε από το Chat (Ανενεργό).',
+ logoutIP: '%s βγήκε από το Chat (Λανθασμένη IP).',
+ logoutKicked: '%s βγήκε από το Chat (Kicked).',
+ channelEnter: '%s μπήκε στο κανάλι.',
+ channelLeave: '%s βγήκε από το κανάλι.',
+ privmsg: '(ψιθυρίζει)',
+ privmsgto: '( ψιθυρίζει σε %s)',
+ invite: '%s σας καλεί να συμμετάσχετε στο %s.',
+ inviteto: 'Η πρόσκληση σας σε %s να συμμετάσχει στο κανάλι %s έχει σταλεί.',
+ uninvite: '%s τερματίζει την πρόσκληση σας για το κανάλι %s.',
+ uninviteto: 'Η πρόσκληση σας σε %s για το κανάλι %s έχει σταλεί.',
+ queryOpen: 'Άνοιξε πρίβε κανάλι σε %s.',
+ queryClose: ' Το πρίβε κανάλι %s έκλεισε.',
+ ignoreAdded: '%s προστέθηκε στη λίστα αγνόησης.',
+ ignoreRemoved: ' %s αφαιρέθηκε από τη λίστα αγνόησης .',
+ ignoreList: 'Αγνοήμενοι χρήστες:',
+ ignoreListEmpty: 'Δεν υπάρχουν αγνοημένοι χρήστες.',
+ who: 'Χρήστες παρόν:',
+ whoChannel: 'Χρήστες συνδεδεμένοι στο κανάλι %s:',
+ whoEmpty: 'Δεν υπάρχουν χρήστες στο συγκεκριμένο κανάλι.',
+ list: 'Διαθέσιμα κανάλια:',
+ bans: 'Αποκλεισμένοι χρήστες:',
+ bansEmpty: 'Δεν υπάρχουν αποκλεισμένοι χρήστες.',
+ unban: 'Ο αποκλεισμός %s αφαιρέθηκε.',
+ whois: ' %s - IP διεύθυνση:',
+ whereis: 'Χρήστης %s είναι στο κανάλι %s.',
+ roll: '%s ρίχνει %s και φέρνει %s.',
+ nick: '%s άλλαξε το όνομα σε %s.',
+ toggleUserMenu: 'Αλλαγή μενού χρήστη για %s',
+ userMenuLogout: 'Αποσύνδεση',
+ userMenuWho: 'Εμφάνιση λίστας συνδεδεμένων',
+ userMenuList: 'Εμφάνιση λίστας διαθέσιμων καναλιών',
+ userMenuAction: 'Περιγραφή ενέργειας',
+ userMenuRoll: 'Ρίξιμο ζαριών',
+ userMenuNick: 'Αλλαγή ονόματος',
+ userMenuEnterPrivateRoom: 'Εισαγωγή σε πριβέ δωμάτιο',
+ userMenuSendPrivateMessage: 'Αποστολή προσωπικού μηνύματος',
+ userMenuDescribe: 'Αποστολή προσωπικής ενέργειας',
+ userMenuOpenPrivateChannel: 'Άνοιγμα πριβέ καναλιού',
+ userMenuClosePrivateChannel: 'Κλείσιμο πριβέ καναλιού',
+ userMenuInvite: 'Πρόσκληση',
+ userMenuUninvite: 'Ακύρωση πρόσκλησης',
+ userMenuIgnore: 'Αγνόηση/Αποδοχή',
+ userMenuIgnoreList: 'Εμφάνιση λίστας αγνοημένων',
+ userMenuWhereis: 'Εμφάνιση καναλιού',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'Εμφάνιση λίστας αποκλεισμένων',
+ userMenuWhois: 'Εμφάνιση IP',
+ unbanUser: 'Επαναφορά αποκλεισμού για %s',
+ joinChannel: 'Μπαίνει στο κανάλι %s',
+ cite: '%s είπε:',
+ urlDialog: 'παρακαλούμε εισάγετε την διεύθυνση (URL) της ιστοσελίδας:',
+ deleteMessage: 'Διαγραφή αυτού του μηνύματος',
+ deleteMessageConfirm: 'Θέλετε να διαγράψετε το επιλεγμένο μήνυμα?',
+ errorCookiesRequired: 'Τα cookies είναι απαραίτητα για το chat.',
+ errorUserNameNotFound: 'Σφάλμα: Ο χρήστης %s δεν βρέθηκε.',
+ errorMissingText: 'Σφάλμα: Λείπει το μήνυμα.',
+ errorMissingUserName: ': Λείπει ο χρήστης.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Σφάλμα: Λείπει το όνομα του καναλιού.',
+ errorInvalidChannelName: 'Σφάλμα: Ακατάλληλο όνομα καναλιού: %s',
+ errorPrivateMessageNotAllowed: 'Σφάλμα: Τα προσωπικά μηνύματα δεν επιτρέπονται.',
+ errorInviteNotAllowed: 'Σφάλμα: Δεν σας επιτρέπετε να καλέσετε άλλούς στο κανάλι.',
+ errorUninviteNotAllowed: 'Σφάλμα: Δεν σας επιτρέπετε να τερματίσετε την πρόσκληση άλλων από το κανάλι.',
+ errorNoOpenQuery: ': Δεν ανοίχθηκε πρίβε κανάλι.',
+ errorKickNotAllowed: 'Δεν σας επιτρέπετε να πετάξετε %s.',
+ errorCommandNotAllowed: 'Σφάλμα: Δεν επιτρέπετε η εντολή: %s',
+ errorUnknownCommand: 'Σφάλμα: Άγνωστη εντολή: %s',
+ errorMaxMessageRate: 'Σφάλμα: Υπερβήκατε τον μέγιστο αριθμό μηνυμάτων ανά λεπτό.',
+ errorConnectionTimeout: 'Σφάλμα: Έληξε ο χρόνος σύνδεσης. Προσπαθήστε ξανά.',
+ errorConnectionStatus: 'Σφάλμα: Κατάσταση σύνδεσης: %s',
+ errorSoundIO: 'Σφάλμα: Απέτυχε η φόρτωση του αρχείου ήχου (Flash IO Σφάλμα).',
+ errorSocketIO: 'Σφάλμα: Η σύνδεση στο socket του διακομιστή απέτυχε (Flash IO Σφάλμα).',
+ errorSocketSecurity: 'Σφάλμα:Η σύνδεση στο socket του διακομιστή απέτυχε (Σφάλμα ασφαλείας του Flash ).',
+ errorDOMSyntax: 'Σφάλμα: Άκυρη DOM σύνταξη (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/en.js b/library/ajaxchat/chat/js/lang/en.js
new file mode 100644
index 000000000..16b4ab472
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/en.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s logs into the Chat.',
+ logout: '%s logs out of the Chat.',
+ logoutTimeout: '%s has been logged out (Timeout).',
+ logoutIP: '%s has been logged out (Invalid IP address).',
+ logoutKicked: '%s has been logged out (Kicked).',
+ channelEnter: '%s enters the channel.',
+ channelLeave: '%s leaves the channel.',
+ privmsg: '(whispers)',
+ privmsgto: '(whispers to %s)',
+ invite: '%s invites you to join %s.',
+ inviteto: 'Your invitation to %s to join channel %s has been sent.',
+ uninvite: '%s uninvites you from channel %s.',
+ uninviteto: 'Your uninvitation to %s for channel %s has been sent.',
+ queryOpen: 'Private channel opened to %s.',
+ queryClose: 'Private channel to %s closed.',
+ ignoreAdded: 'Added %s to the ignore list.',
+ ignoreRemoved: 'Removed %s from the ignore list.',
+ ignoreList: 'Ignored Users:',
+ ignoreListEmpty: 'No ignored Users listed.',
+ who: 'Online Users:',
+ whoChannel: 'Online Users in channel %s:',
+ whoEmpty: 'No online users in the given channel.',
+ list: 'Available channels:',
+ bans: 'Banned Users:',
+ bansEmpty: 'No banned Users listed.',
+ unban: 'Ban of user %s revoked.',
+ whois: 'User %s - IP address:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s rolls %s and gets %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Change username',
+ userMenuEnterPrivateRoom: 'Enter private room',
+ userMenuSendPrivateMessage: 'Send private message',
+ userMenuDescribe: 'Send private action',
+ userMenuOpenPrivateChannel: 'Open private channel',
+ userMenuClosePrivateChannel: 'Close private channel',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'List ignored users',
+ userMenuWhereis: 'Display channel',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'List banned users',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'Join channel %s',
+ cite: '%s said:',
+ urlDialog: 'Please enter the address (URL) of the webpage:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'Cookies are required for this chat.',
+ errorUserNameNotFound: 'Error: User %s not found.',
+ errorMissingText: 'Error: Missing message text.',
+ errorMissingUserName: 'Error: Missing username.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Error: Missing channel name.',
+ errorInvalidChannelName: 'Error: Invalid channel name: %s',
+ errorPrivateMessageNotAllowed: 'Error: Private messages are not allowed.',
+ errorInviteNotAllowed: 'Error: You are not allowed to invite someone to this channel.',
+ errorUninviteNotAllowed: 'Error: You are not allowed to uninvite someone from this channel.',
+ errorNoOpenQuery: 'Error: No private channel open.',
+ errorKickNotAllowed: 'Error: You are not allowed to kick %s.',
+ errorCommandNotAllowed: 'Error: Command not allowed: %s',
+ errorUnknownCommand: 'Error: Unknown command: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'Error: Connection timeout. Please try again.',
+ errorConnectionStatus: 'Error: Connection status: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/es.js b/library/ajaxchat/chat/js/lang/es.js
new file mode 100644
index 000000000..393467a8c
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/es.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Manu Quintans / KeScI [www.e-nologia.com]
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s entra al Chat.',
+ logout: '%s sale del Chat.',
+ logoutTimeout: '%s se ha desconectado (Tiempo de espera agotado).',
+ logoutIP: '%s se ha desconectado (Direccion IP no valida).',
+ logoutKicked: '%s se ha desconectado (Pateado).',
+ channelEnter: '%s entra en el canal.',
+ channelLeave: '%s se va del canal.',
+ privmsg: '(susurra)',
+ privmsgto: '(susurra a %s)',
+ invite: '%s te invita a unirte a %s.',
+ inviteto: 'Su invitación a %s para unirse al canal %s se ha enviado.',
+ uninvite: '%s le retira la invitación del canal %s.',
+ uninviteto: 'Su retirada de invitación a %s para el canal %s se ha enviado.',
+ queryOpen: 'Privado abierto a %s.',
+ queryClose: 'Privado cerrado a %s.',
+ ignoreAdded: 'Agregado %s a la lista de usuarios ignorados.',
+ ignoreRemoved: 'Eliminado %s de la lista de usuarios ignorados.',
+ ignoreList: 'Usuarios ignorados',
+ ignoreListEmpty: 'Lista de usuarios no ignorados.',
+ who: 'Usuarios conectados:',
+ whoChannel: 'Usuarios conectados en el canal %s:',
+ whoEmpty: 'No hay usuarios conectados en este momento.',
+ list: 'Canales disponibles:',
+ bans: 'Usuarios Baneados:',
+ bansEmpty: 'No se han listado usuarios baneados.',
+ unban: 'Ban del usuario %s retirado.',
+ whois: 'Usuario %s - Direccion IP:',
+ whereis: 'Usuario %s está en el canal %s.',
+ roll: '%s lanza %s y obtiene un %s.',
+ nick: '%s es ahora %s.',
+ toggleUserMenu: 'Abrir/Cerrar menú del usuario %s',
+ userMenuLogout: 'Desconectar',
+ userMenuWho: 'Mostrar usuarios conectados',
+ userMenuList: 'Mostrar canales disponibles',
+ userMenuAction: 'Describir acción',
+ userMenuRoll: 'Tirar dado',
+ userMenuNick: 'Cambiar Nombre de Usuario',
+ userMenuEnterPrivateRoom: 'Entrar en canal privado',
+ userMenuSendPrivateMessage: 'Enviar mensaje privado',
+ userMenuDescribe: 'Enviar acción privada',
+ userMenuOpenPrivateChannel: 'Abrir canal privado',
+ userMenuClosePrivateChannel: 'Cerrar canal privado',
+ userMenuInvite: 'Invitar',
+ userMenuUninvite: 'Quitar invitación',
+ userMenuIgnore: 'Ignorar/Aceptar',
+ userMenuIgnoreList: 'Mostrar usuarios ignorados',
+ userMenuWhereis: 'Mostrar canal',
+ userMenuKick: 'Patada/Ban',
+ userMenuBans: 'Mostrar usuarios baneados',
+ userMenuWhois: 'Mostrar la IP',
+ unbanUser: 'Quitar el ban al usuario %s',
+ joinChannel: 'Entrar al canal %s',
+ cite: '%s dijo:',
+ urlDialog: 'Por favor intruduzca la dirección (URL) de la página web:',
+ deleteMessage: 'Borrar este mensaje del chat',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'Se necesitan las Cookies para este chat.',
+ errorUserNameNotFound: 'Error: usuario %s no se ha encontrado.',
+ errorMissingText: 'Error: Mensaje perdido.',
+ errorMissingUserName: 'Error: Usuario no encontrado.',
+ errorInvalidUserName: 'Error: Nombre de usuario no válido.',
+ errorUserNameInUse: 'Error: Nombre de usuario está en uso.',
+ errorMissingChannelName: 'Error: No se encuentra el canal.',
+ errorInvalidChannelName: 'Error: Nombre invalido del canal: %s',
+ errorPrivateMessageNotAllowed: 'Error: No se permiten mensajes privados.',
+ errorInviteNotAllowed: 'Error: No está autorizado a invitar a alguien a este canal.',
+ errorUninviteNotAllowed: 'Error: No está autorizado a quitar la invitación a alguien de este canal.',
+ errorNoOpenQuery: 'Error: Ningún privado abierto.',
+ errorKickNotAllowed: 'Error: No está autorizado a patear a %s.',
+ errorCommandNotAllowed: 'Error: Comando no permitido: %s',
+ errorUnknownCommand: 'Error: Comando desconocido: %s',
+ errorMaxMessageRate: 'Error: Ha sobrepasado el número máximo de mensajes por minuto.',
+ errorConnectionTimeout: 'Error: Connection timeout. Please try again.',
+ errorConnectionStatus: 'Error: Estado de la conexión: %s',
+ errorSoundIO: 'Error: No se ha podido cargar el fichero de sonido (Error IO Flash).',
+ errorSocketIO: 'Error: No se ha podido conectar al servidor socket (Error IO Flash).',
+ errorSocketSecurity: 'Error: No se ha podido conectar al servidor socket (Error Seguridad Flash).',
+ errorDOMSyntax: 'Error: Sintaxis DOM No Válida (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/et.js b/library/ajaxchat/chat/js/lang/et.js
new file mode 100644
index 000000000..e83c986b9
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/et.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s logis jutukasse.',
+ logout: '%s logis jutukast välja.',
+ logoutTimeout: '%s logiti jutukast välja (Aeg otsas).',
+ logoutIP: '%s logiti jutukast välja (Vigane IP aadress).',
+ logoutKicked: '%s logiti jutukast välja (Välja heidetud).',
+ channelEnter: '%s sisenes kanalisse.',
+ channelLeave: '%s lahkus kanalist.',
+ privmsg: '(sosinad)',
+ privmsgto: '(sosinad %s -le)',
+ invite: '%s kutsub sind %s.',
+ inviteto: 'Sinu kutse %s -le ühineda kanaliga %s saadeti ära.',
+ uninvite: '%s palub sul lahkuda kanalist %s.',
+ uninviteto: 'Sinu palve %s -le lahkuda kanalist %s saadeti ära.',
+ queryOpen: 'Privaat kanal avati %s -le.',
+ queryClose: 'Privaat kanal %s -le suleti.',
+ ignoreAdded: ' %s -t ignoreeritakse.',
+ ignoreRemoved: ' %s ignoreerimine tühistati.',
+ ignoreList: 'Ignoreeritud kasutajad:',
+ ignoreListEmpty: 'Ignoreeritud kasutajad puuduvad.',
+ who: 'Sisse loginud kasutajad:',
+ whoChannel: 'Sisse loginud kasutajad kanalis %s:',
+ whoEmpty: 'Antud kanalis sisse loginud kasutajaid ei ole.',
+ list: 'Vabad kanalid:',
+ bans: 'Kasutajate must nimekiri:',
+ bansEmpty: 'Mustas nimekirjas kasutajaid ei ole.',
+ unban: 'Kasutaja %s eemaldati mustast nimekirjast.',
+ whois: 'Kasutaja %s - IP aadress:',
+ whereis: 'Kasutaja %s on kanalis %s.',
+ roll: '%s veeretas %s ja sai %s.',
+ nick: '%s nimetas end ümber: %s.',
+ toggleUserMenu: 'Näita/ära näita kasutaja menüüd',
+ userMenuLogout: 'Lahku',
+ userMenuWho: 'Näita sisse loginud kasutajaid',
+ userMenuList: 'Näita vabad kanalid',
+ userMenuAction: 'Kirjelda tegevust',
+ userMenuRoll: 'Veereta täringut',
+ userMenuNick: 'Muuda kasutajanimi',
+ userMenuEnterPrivateRoom: 'Sisene privaat-ruumi',
+ userMenuSendPrivateMessage: 'Saada privaat-sõnum',
+ userMenuDescribe: 'Saada privaat-tegevus',
+ userMenuOpenPrivateChannel: 'Ava privaat-kanal',
+ userMenuClosePrivateChannel: 'Sulge privaat-kanal',
+ userMenuInvite: 'Kutsu',
+ userMenuUninvite: 'Palu lahkuda',
+ userMenuIgnore: 'Ignoreeri/Tunnusta',
+ userMenuIgnoreList: 'Ignoreeritud kasutajad',
+ userMenuWhereis: 'Asukoha kanal',
+ userMenuKick: 'Viska välja/Lisa musta nimekirja',
+ userMenuBans: 'Musta nimekirja kasutajad',
+ userMenuWhois: 'Näita IP-d',
+ unbanUser: 'Eemalda %s mustast nimekirjast',
+ joinChannel: 'Liitu kanaliga %s',
+ cite: '%s ütles:',
+ urlDialog: 'Palun sisesta oma veebilehe (URL):',
+ deleteMessage: 'Kustuta see jutuka teade',
+ deleteMessageConfirm: 'Kas tahad tõesti kustutada seda sõnumit??',
+ errorCookiesRequired: 'Luba "küpsised", et kasutada seda jutukat.',
+ errorUserNameNotFound: 'Viga: Kasutajat nimega %s ei leitud.',
+ errorMissingText: 'Viga: Sõnumi tekst kadunud.',
+ errorMissingUserName: 'Viga: Kasutajanimi puuduv.',
+ errorInvalidUserName: 'Viga: Vigane kasutajanimi.',
+ errorUserNameInUse: 'Viga: Kasutajanimi on juba võetud.',
+ errorMissingChannelName: 'Viga: Kanali nimi on kadunud.',
+ errorInvalidChannelName: 'Viga: Vigane kanali nimi: %s',
+ errorPrivateMessageNotAllowed: 'Viga: Privaat-sõnumid ei ole lubatud.',
+ errorInviteNotAllowed: 'Viga: Sul ei ole lubatud kutsuda kedagi siia kanalisse.',
+ errorUninviteNotAllowed: 'Viga: Sul ei ole lubatud kedagi sellest kanalist lahkuma paluda.',
+ errorNoOpenQuery: 'Viga: htegi privaat-kanalit pole avatud.',
+ errorKickNotAllowed: 'Viga: Sul ei ole lubatud välja visata %s.',
+ errorCommandNotAllowed: 'Viga: Korraldus pole lubatud: %s',
+ errorUnknownCommand: 'Viga: Tundmatu korraldus: %s',
+ errorMaxMessageRate: 'Viga: Sinu maksimum sõnumite hulk, minuti vältel, on ületatud.',
+ errorConnectionTimeout: 'Viga: hendus aegus. Please proovi uuesti.',
+ errorConnectionStatus: 'Viga: henduse olek: %s',
+ errorSoundIO: 'Viga: Helifaili ei õnnestunud laadida (Flash IO Viga).',
+ errorSocketIO: 'Viga: hendus socket serveriga ebaõnnestus (Flash IO Viga).',
+ errorSocketSecurity: 'Viga: hendus socket serveriga ebaõnnestus (Flash Turvalisuse Viga).',
+ errorDOMSyntax: 'Viga: Vigane DOM Süntaks (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/fi.js b/library/ajaxchat/chat/js/lang/fi.js
new file mode 100644
index 000000000..68a536c73
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/fi.js
@@ -0,0 +1,93 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Asmo Soinio
+ * @author Saku Laukkanen
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s kirjautui sisään.',
+ logout: '%s kirjautui ulos.',
+ logoutTimeout: '%s kirjautui ulos (Aikakatkaisu).',
+ logoutIP: '%s kirjautui ulos (virheellinen IP-osoite).',
+ logoutKicked: '%s kirjautui ulos (Potkut).',
+ channelEnter: '%s liittyi kanavalle.',
+ channelLeave: '%s poistui kanavalta.',
+ privmsg: '(kuiskaa)',
+ privmsgto: '(kuiskaa käyttäjälle %s)',
+ invite: '%s kutsuu sinut liittymään kanavalle %s.',
+ inviteto: 'Sinun kutsusi käyttäjälle %s, liittymisestä kanavalle %s, on lähetetty.',
+ uninvite: '%s peruu kutsun kanavalle %s.',
+ uninviteto: 'Kutsusi peruminen käyttäjälle %s kanavaa %s varten, on lähetetty.',
+ queryOpen: 'Yksityinen kanava käyttäjälle %s on avattu.',
+ queryClose: 'Yksityinen kanava käyttäjälle %s on suljettu.',
+ ignoreAdded: 'Käyttäjä %s on lisätty huomiotta jätettäviin.',
+ ignoreRemoved: 'Käyttäjä %s on poistettu huomiotta jätettävistä.',
+ ignoreList: 'Huomiotta jätettävät käyttäjät:',
+ ignoreListEmpty: 'Ei huomiotta jätettäviä käyttäjiä.',
+ who: 'Paikallaolijat:',
+ whoChannel: 'Paikallaolijat kanavalla %s:',
+ whoEmpty: 'Ei käyttäjiä annetulla kanavalla.',
+ list: 'Käytettävät kanavat:',
+ bans: 'Potkitut käyttäjät:',
+ bansEmpty: 'Ei potkittuja käyttäjiä.',
+ unban: 'Käyttäjän %s potkut on poistettu.',
+ whois: 'Käyttäjän %s IP osoite:',
+ whereis: 'Käyttäjä %s on kanavalla %s.',
+ roll: '%s heittää %s ja saa %s.',
+ nick: '%s on nyt %s.',
+ toggleUserMenu: 'Näytä/piilota valikko käyttäjälle %s',
+ userMenuLogout: 'Poistu',
+ userMenuWho: 'Listaa paikallaolijat',
+ userMenuList: 'Listaa käytettävissä olevat kanavat',
+ userMenuAction: 'Määrittele toiminta',
+ userMenuRoll: 'Heitä noppaa',
+ userMenuNick: 'Vaihda käyttäjätunnusta',
+ userMenuEnterPrivateRoom: 'Mene yksityiseen kanavaasi',
+ userMenuSendPrivateMessage: 'Lähetä yksityinen viesti',
+ userMenuDescribe: 'Lähetä yksityinen toiminto',
+ userMenuOpenPrivateChannel: 'Avaa yksityinen kanava',
+ userMenuClosePrivateChannel: 'Sulje yksityinen kanava',
+ userMenuInvite: 'Kutsu',
+ userMenuUninvite: 'Peru kutsu',
+ userMenuIgnore: 'Ohita/Hyväksy',
+ userMenuIgnoreList: 'Listaa huomiota jätettävät käyttäjät',
+ userMenuWhereis: 'Näytä kanavat',
+ userMenuKick: 'Poista/Porttikielto',
+ userMenuBans: 'Listaa käyttäjät, joilla porttikielto',
+ userMenuWhois: 'Näytä IP-osoite',
+ unbanUser: 'Poista käyttäjän %s porttikielto',
+ joinChannel: 'Liity kanavalle %s',
+ cite: '%s sanoi:',
+ urlDialog: 'Lisää nettisivujen osoite (URL):',
+ deleteMessage: 'Poista tämä viesti',
+ deleteMessageConfirm: 'Poistetaanko viesti?',
+ errorCookiesRequired: 'Evästeiden pitää olla sallituja käyttääksesi tätä keskustelua.',
+ errorUserNameNotFound: 'Virhe: Käyttäjää %s ei löydetty.',
+ errorMissingText: 'Virhe: Puuttuva viestin teksti.',
+ errorMissingUserName: 'Virhe: Puuttuva käyttäjänimi.',
+ errorInvalidUserName: 'Virhe: Virheellinen käyttäjätunnus.',
+ errorUserNameInUse: 'Virhe: Käyttäjätunnus on jo käytössä.',
+ errorMissingChannelName: 'Virhe: Puuttuva kanavan nimi.',
+ errorInvalidChannelName: 'Virhe: Virheellinen kanavan nimi: %s',
+ errorPrivateMessageNotAllowed: 'Virhe: Yksityisviestit eivät ole sallittuja.',
+ errorInviteNotAllowed: 'Virhe: Sinulla ei ole oikeutta kutsua ketään kanavalle.',
+ errorUninviteNotAllowed: 'Virhe: Sinulla ei ole oikeutta perua kutsua tälle kanavalle.',
+ errorNoOpenQuery: 'Virhe: Ei yksityistä kanavaa auki.',
+ errorKickNotAllowed: 'Virhe: Sinulla ei ole oikeutta potkia käyttäjää %s.',
+ errorCommandNotAllowed: 'Virhe: Komento ei ole sallittu: %s',
+ errorUnknownCommand: 'Virhe: Tuntematon komento: %s',
+ errorMaxMessageRate: 'Virhe: Liikaa viestejä minuutissa.',
+ errorConnectionTimeout: 'Virhe: Yhteyden aikakatkaisu, olkaa hyvä ja yrittäkää uudelleen.',
+ errorConnectionStatus: 'Virhe: Yhteyden tila: %s',
+ errorSoundIO: 'Virhe: Äänitiedoston lataus epäonnistui (Flash IO-virhe).',
+ errorSocketIO: 'Virhe: Yhteys socket palvelimeen epäonnistui (Flash IO-virhe).',
+ errorSocketSecurity: 'Virhe: Yhteys socket palvelimeen epäonnistui (Flash-turvallisuus virhe).',
+ errorDOMSyntax: 'Virhe: Virheellinen DOM-syntaksi (DOM-tunniste: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/fr.js b/library/ajaxchat/chat/js/lang/fr.js
new file mode 100644
index 000000000..35846f95e
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/fr.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @contributors Ettelcar, Massimiliano Tiraboschi, Xytovl
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s se connecte au Chat.',
+ logout: '%s se déconnecte du Chat.',
+ logoutTimeout: '%s a été déconnecté (Temps écoulé).',
+ logoutIP: '%s a été déconnecté (Adresse IP invalide).',
+ logoutKicked: '%s a été déconnecté (Éjecté).',
+ channelEnter: '%s entre dans le salon.',
+ channelLeave: '%s sort du salon.',
+ privmsg: '(murmure)',
+ privmsgto: '(murmure à l’oreille de %s)',
+ invite: '%s vous invite à rejoindre %s.',
+ inviteto: 'Votre invation pour %s à rejoindre le salon %s a bien été envoyée.',
+ uninvite: '%s annule son invitation pour le salon %s.',
+ uninviteto: 'Votre annulaton d’invitation pour %s au salon %s a bien été envoyée.',
+ queryOpen: 'Salon privé ouvert sous le titre %s.',
+ queryClose: 'Le salon privé %s a été fermé.',
+ ignoreAdded: '%s a été ajouté à la liste des personnes ignorées.',
+ ignoreRemoved: '%s a été enlevé de la liste des personnes ignorées.',
+ ignoreList: 'Utilisateurs ignorés:',
+ ignoreListEmpty: 'Aucun utilisateur ignoré référencé.',
+ who: 'Utilisateurs en ligne:',
+ whoChannel: 'Utilisateurs en ligne dans le salon %s :',
+ whoEmpty: 'Aucun utilisateur en ligne dans le salon concerné.',
+ list: 'Salons disponibles :',
+ bans: 'Utilisateurs bannis :',
+ bansEmpty: 'Aucun utilisateur banni référencé.',
+ unban: 'Le ban de l’utilisateur %s a été levé.',
+ whois: 'Utilisateur %s - Adresse IP:',
+ whereis: 'L’utilisateur %s est dans le salon %s.',
+ roll: '%s jette %s et obtient %s.',
+ nick: '%s est maintenant %s.',
+ toggleUserMenu: 'Montrer/cacher menu pour %s',
+ userMenuLogout: 'Déconnexion',
+ userMenuWho: 'Liste membres en ligne',
+ userMenuList: 'Liste salons disponibles',
+ userMenuAction: 'Décrire une action',
+ userMenuRoll: 'Jeter un dé',
+ userMenuNick: 'Changer nom',
+ userMenuEnterPrivateRoom: 'Rejoindre un salon privé',
+ userMenuSendPrivateMessage: 'Envoyer un message privé',
+ userMenuDescribe: 'Envoyer une action privé',
+ userMenuOpenPrivateChannel: 'Ouvrir un salon privé',
+ userMenuClosePrivateChannel: 'Fermer un salon privé',
+ userMenuInvite: 'Inviter',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignorer/Accepter',
+ userMenuIgnoreList: 'Liste utilisateurs ignorés',
+ userMenuWhereis: 'Montrer les salons',
+ userMenuKick: 'Éjecter/bannir',
+ userMenuBans: 'Liste utilisateurs bannis',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'Rejoindre le salon %s',
+ cite: '%s a dit:',
+ urlDialog: 'Veuillez entrer l’addresse (URL) de la page web:',
+ deleteMessage: 'Effacer ce message',
+ deleteMessageConfirm: 'Effacer le message selectionné ?',
+ errorCookiesRequired: 'Ce Chat requiert l’acceptation des cookies.',
+ errorUserNameNotFound: 'Erreur : Utilisateur %s introuvable.',
+ errorMissingText: 'Erreur : Texte du message manquant.',
+ errorMissingUserName: 'Erreur : Nom d’utilisateur manquant.',
+ errorMissingChannelName: 'Erreur : Nom de salon manquant.',
+ errorInvalidChannelName: 'Erreur : Mauvais nom de salon: %s',
+ errorPrivateMessageNotAllowed: 'Erreur : Les messages privés sont interdits.',
+ errorInviteNotAllowed: 'Erreur : Vous n’êtes pas autorisé à inviter quelqu’un à ce salon.',
+ errorUninviteNotAllowed: 'Erreur : Vous n’êtes pas autorisé à annuler une invitation à ce salon.',
+ errorNoOpenQuery: 'Erreur : Aucun salon privé ouvert.',
+ errorKickNotAllowed: 'Erreur : Vous n’êtes pas autorisé à éjecter %s.',
+ errorCommandNotAllowed: 'Erreur : Commande interdite: %s',
+ errorUnknownCommand: 'Erreur : Commande inconnue: %s',
+ errorMaxMessageRate: 'Error : You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'Erreur : Temps de connexion écoulé. Veuillez réessayer.',
+ errorConnectionStatus: 'Erreur : Statut de connexion: %s',
+ errorSoundIO: 'Erreur : Impossible de charger le fichier son (Erreur E/S Flash).',
+ errorSocketIO: 'Erreur : Connexion au serveur échouée (Erreur E/S Flash).',
+ errorSocketSecurity: 'Erreur : Connexion au serveur échouée (Erreur de sécurité Flash).',
+ errorDOMSyntax: 'Erreur : Syntaxe DOM invalide (ID DOM : %s).'
+
+}
+
+
diff --git a/library/ajaxchat/chat/js/lang/gl.js b/library/ajaxchat/chat/js/lang/gl.js
new file mode 100644
index 000000000..314e226f8
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/gl.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Manu Quintans
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s logs dentro de Chat.',
+ logout: '%s logs fora del Chat.',
+ logoutTimeout: '%s desconectouse(Tempo de espera esgotado).',
+ logoutIP: '%s desconectouse (Dirección IP non válida ).',
+ logoutKicked: '%s desconectouse (Pateado).',
+ channelEnter: '%s Entra no chat.',
+ channelLeave: '%s Vaise do chat.',
+ privmsg: '(whispers)',
+ privmsgto: '(whispers to %s)',
+ invite: '%s invítache a unirte a %s.',
+ inviteto: 'A túa invitación a %s para unirse a %s foi enviada.',
+ uninvite: '%s rechazado en %s.',
+ uninviteto: 'O teu rechazo a %s para %s foi enviado.',
+ queryOpen: 'Chat privado aberto %s.',
+ queryClose: 'Chat privado pechado %s pechado.',
+ ignoreAdded: 'Engadido %s a lista de usuarios ignorados.',
+ ignoreRemoved: 'Eliminado %s da lista de usuarios ignorados.',
+ ignoreList: 'Usuarios ignorados',
+ ignoreListEmpty: 'Lista de usuarios non ignorados.',
+ who: 'Usuarios conectados:',
+ whoChannel: 'Usuarios en liña na canle %s:',
+ whoEmpty: 'Non hai usuarios conectados neste momento.',
+ list: 'Chats disponibles:',
+ bans: 'Usuarios Baneados:',
+ bansEmpty: 'Non hai usuarios baneados.',
+ unban: 'Baneo do usuario %s revocado.',
+ whois: 'Usuario %s - Direccion IP:',
+ whereis: 'Usuario %s en chat %s.',
+ roll: '%s rolls %s e toma %s.',
+ nick: '%s agora como %s.',
+ toggleUserMenu: 'Cambiar menu de usuario para %s',
+ userMenuLogout: 'Sair',
+ userMenuWho: 'Listar usuarios en liña',
+ userMenuList: 'Canles disponibles',
+ userMenuAction: 'Describe acción',
+ userMenuRoll: 'Roll di',
+ userMenuNick: 'Cambiar nome de usuario',
+ userMenuEnterPrivateRoom: 'Entrar nun privado',
+ userMenuSendPrivateMessage: 'Enviar mensaxe privada',
+ userMenuDescribe: 'Enviar accion en privado',
+ userMenuOpenPrivateChannel: 'Abrir privado',
+ userMenuClosePrivateChannel: 'Pechar privado',
+ userMenuInvite: 'Invitar',
+ userMenuUninvite: 'Rechazar invitado',
+ userMenuIgnore: 'Ignorar/Aceptar',
+ userMenuIgnoreList: 'Lista usuarios ignorados',
+ userMenuWhereis: 'Amosar canle',
+ userMenuKick: 'Banear',
+ userMenuBans: 'Lista usuarios baneados',
+ userMenuWhois: 'Amosar IP',
+ unbanUser: 'Eliminar baneo de %s',
+ joinChannel: 'Unirte a %s',
+ cite: '%s dixo:',
+ urlDialog: 'Por favor, introduce a URL da paxina web:',
+ deleteMessage: 'Eliminar mensaxe',
+ deleteMessageConfirm: 'Queres borra-la mensaxe?',
+ errorCookiesRequired: 'As Cookies son necesarias para o chat.',
+ errorUserNameNotFound: 'Error: usuario %s non encontrado.',
+ errorMissingText: 'Error: mensaxe perdida.',
+ errorMissingUserName: 'Error: Usuario non encontrado.',
+ errorInvalidUserName: 'Error: Nome de usuario non valido.',
+ errorUserNameInUse: 'Error: Usuario en uso.',
+ errorMissingChannelName: 'Error: No se atopa a canle.',
+ errorInvalidChannelName: 'Error: Nome inválido de canle: %s',
+ errorPrivateMessageNotAllowed: 'Error: mensaxes privadas non permitidas.',
+ errorInviteNotAllowed: 'Error: Non se che permite invitar nesta canle.',
+ errorUninviteNotAllowed: 'Error: Non se che permite rechazar invitados nesta canle.',
+ errorNoOpenQuery: 'Error: Ningunha canle privado aberto.',
+ errorKickNotAllowed: 'Error: Non podes banear %s.',
+ errorCommandNotAllowed: 'Error: Comando non permitido: %s',
+ errorUnknownCommand: 'Error: Comando descoñecido: %s',
+ errorMaxMessageRate: 'Error: Excedes o numero maximo de mensaxes por minuto.',
+ errorConnectionTimeout: 'Error: Tempo superado. Téntao de novo.',
+ errorConnectionStatus: 'Error: Estado de conexión: %s',
+ errorSoundIO: 'Error: Error o reproducir son(Flash IO Error).',
+ errorSocketIO: 'Error: Conexión co servidor fallida (Flash IO Error).',
+ errorSocketSecurity: 'Error: Conexión co servidor fallida(Flash Security Error).',
+ errorDOMSyntax: 'Error: Sintaxis DOM Inválida(DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/he.js b/library/ajaxchat/chat/js/lang/he.js
new file mode 100644
index 000000000..94bbdc5e1
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/he.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Smiley Barry
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s נכנס לתוך הצאט.',
+ logout: '%s יוצא מהצאט.',
+ logoutTimeout: '%s הוצא מהצאט (היה לא זמין).',
+ logoutIP: '%s הוצא מהצאט (כתובת מחשב בלתי חוקית).',
+ logoutKicked: '%s הוצא מהצאט (הועף/נבעט).',
+ channelEnter: '%s נכנס לתוך הערוץ.',
+ channelLeave: '%s יוצא מהערוץ.',
+ privmsg: '(לוחש)',
+ privmsgto: '(לוחש ל%s)',
+ invite: '%s מזמין אותך להצטרף לערוץ %s.',
+ inviteto: 'ההזמנה שלך עבור %s להצטרף לערוץ %s נשלחה.',
+ uninvite: '%s ביטל את הזמנתו לערוץ %s.',
+ uninviteto: 'ביטול ההזמנה שלך עבור %s להצטרף לערוץ %s נשלח.',
+ queryOpen: 'ערוץ פרטי עבור %s נפתח.',
+ queryClose: 'ערוץ פרטי עבור %s נסגר.',
+ ignoreAdded: 'המשתמש %s נוסף לרשימת ההתעלמות.',
+ ignoreRemoved: 'המשתמש %s נמחק מרשימת ההתעלמות.',
+ ignoreList: 'משתמשים אשר אתה מתעלם מהם:',
+ ignoreListEmpty: 'אין משתמשים ברשימה.',
+ who: 'משתמשים מחוברים:',
+ whoChannel: 'Online Users in channel %s:',
+ whoEmpty: 'אין משתמשים מחוברים בערוץ.',
+ list: 'ערוצים פתוחים:',
+ bans: 'משתמשים חסומים:',
+ bansEmpty: 'אין משתמשים חסומים.',
+ unban: 'בוטלה החסימה נגד המשתמש %s.',
+ whois: 'כתובת המחשב של המשתמש %s:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s מגלגל %s ומקבל %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Change username',
+ userMenuEnterPrivateRoom: 'Enter private room',
+ userMenuSendPrivateMessage: 'Send private message',
+ userMenuDescribe: 'Send private action',
+ userMenuOpenPrivateChannel: 'Open private channel',
+ userMenuClosePrivateChannel: 'Close private channel',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'List ignored users',
+ userMenuWhereis: 'Display channel',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'List banned users',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'הצטרף לערוץ %s',
+ cite: '%s אמר:',
+ urlDialog: 'אנא הכנס את כתובת האינטרנט (URL) של הדף:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'הצאט מבקש עוגיות כדי לפעול. אנא רד לחנות לקנות.',
+ errorUserNameNotFound: 'שגיאה: המשתמש %s לא נמצא.',
+ errorMissingText: 'שגיאה: חסר טקסט בהודעה.',
+ errorMissingUserName: 'שגיאה: חסר שם משתמש.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'שגיאה: חסר שם ערוץ.',
+ errorInvalidChannelName: 'שגיאה: שם ערוץ לא חוקי: %s',
+ errorPrivateMessageNotAllowed: 'שגיאה: הודעות פרטיות אסורות לשימוש.',
+ errorInviteNotAllowed: 'שגיאה: אסור לך להזמין אנשים לערוץ זה.',
+ errorUninviteNotAllowed: 'שגיאה: אסור לך לבטל הזמנות של אנשים לערוץ זה.',
+ errorNoOpenQuery: 'שגיאה: ערוץ פרטי לא פתוח.',
+ errorKickNotAllowed: 'שגיאה: אסור לך להעיף את %s.',
+ errorCommandNotAllowed: 'שגיאה: פקודה אסורה: %s',
+ errorUnknownCommand: 'שגיאה: פקודה לא ידועה: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'שגיאה: זמן חיבור פג. אנא נסה שנית.',
+ errorConnectionStatus: 'שגיאת חיבור: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/hr.js b/library/ajaxchat/chat/js/lang/hr.js
new file mode 100644
index 000000000..6f72e64de
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/hr.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: 'Korisnik %s prijavio se u brbljanje.',
+ logout: 'Korisnik %s odjavio se iz brbljanja.',
+ logoutTimeout: 'Korisnik %s je odjavljen (neaktivnost).',
+ logoutIP: 'Korisnik %s je odjavljen (nepravilna IP adresa).',
+ logoutKicked: 'Korisnik %s je odjavljen (prognan).',
+ channelEnter: 'Korisnik %s pristupa kanalu.',
+ channelLeave: 'Korisnik %s napušta kanal.',
+ privmsg: '(šapuće)',
+ privmsgto: '(šapuće korisniku %s)',
+ invite: 'Korisnik %s poziva vas da se pridružite kanalu %s.',
+ inviteto: 'Vaš poziv korisniku %s da se pridruži kanalu %s je poslan.',
+ uninvite: 'Korisnik %s povukao je svoj poziv za kanal %s.',
+ uninviteto: 'Vaš opoziv korisniku %s za pridruživanje kanalu %s je poslan.',
+ queryOpen: 'Otvoren je privatni kanal za %s.',
+ queryClose: 'Privatni kanal za %s je zatvoren.',
+ ignoreAdded: 'Korisnik %s je dodan na popis ignoriranih.',
+ ignoreRemoved: 'Korisnik %s je uklonjen s popisa ignoriranih.',
+ ignoreList: 'Ignorirani korisnici:',
+ ignoreListEmpty: 'Nema ignoriranih korisnika.',
+ who: 'Prisutni korisnici:',
+ whoChannel: 'Prisutni korisnici u kanalu %s.',
+ whoEmpty: 'U odabranom kanalu nema prisutnih korisnika.',
+ list: 'Dostupni kanali:',
+ bans: 'Zabranjeni korisnici:',
+ bansEmpty: 'Nema zabranjenih korisnika.',
+ unban: 'Opozvana je zabrana korisnika %s.',
+ whois: 'Korisnik %s - IP adresa:',
+ whereis: 'Korisnik %s je u kanalu %s.',
+ roll: 'Korisnik %s baca %s i dobiva %s.',
+ nick: 'Korisnik %s je sad poznat kao %s.',
+ toggleUserMenu: 'Prebaci korisnički zbornik za %s',
+ userMenuLogout: 'Odjava',
+ userMenuWho: 'Ispiši prisutne korisnike',
+ userMenuList: 'Ispiši dostupne kanale',
+ userMenuAction: 'Aktivnost',
+ userMenuRoll: 'Baci kocku',
+ userMenuNick: 'Promijeni korisničko ime',
+ userMenuEnterPrivateRoom: 'Pristupi privatnoj sobi',
+ userMenuSendPrivateMessage: 'Pošalji privatnu poruku',
+ userMenuDescribe: 'Pošalji privatnu aktivnost',
+ userMenuOpenPrivateChannel: 'Otvori privatni kanal',
+ userMenuClosePrivateChannel: 'Zatvori privatni kanal',
+ userMenuInvite: 'Pozovi',
+ userMenuUninvite: 'Opozovi',
+ userMenuIgnore: 'Ignoriraj / Prihvati',
+ userMenuIgnoreList: 'Ispiši ignorirane korisnike',
+ userMenuWhereis: 'Prikaži kanal',
+ userMenuKick: 'Prognaj / Zabrani',
+ userMenuBans: 'Ispiši zabranjene korisnike',
+ userMenuWhois: 'Prikaži IP',
+ unbanUser: 'Opozovi zabranu korisnika %s.',
+ joinChannel: 'Pridruži se kanalu %s',
+ cite: 'Korisnik %s je rekao:',
+ urlDialog: 'Unesite URL adresu web-stranice:',
+ deleteMessage: 'Izbriši ovu poruku',
+ deleteMessageConfirm: 'Želite li zaista izbrisati ovu poruku?',
+ errorCookiesRequired: 'Ovo brbljanje zahtjeva omogućene kolačiće.',
+ errorUserNameNotFound: 'Pogreška: Korisnik %s nije pronađen.',
+ errorMissingText: 'Pogreška: Nedostaje tekst poruke.',
+ errorMissingUserName: 'Pogreška: Nedostaje korisničko ime.',
+ errorInvalidUserName: 'Pogreška: Nepravilno korisničko ime.',
+ errorUserNameInUse: 'Pogreška: Korisničko ime već je u upotrebi.',
+ errorMissingChannelName: 'Pogreška: Nedostaje naziv kanala.',
+ errorInvalidChannelName: 'Pogreška: Nepravilan naziv kanala: %s',
+ errorPrivateMessageNotAllowed: 'Pogreška: Privatne poruke nisu dopuštene.',
+ errorInviteNotAllowed: 'Pogreška: Nemate dopuštenja za pozivanje drugih osoba u ovaj kanal.',
+ errorUninviteNotAllowed: 'Pogreška: Nemate dopuštenja za opozivanje drugih osoba u ovom kanalu.',
+ errorNoOpenQuery: 'Pogreška: Nema otvorenog privatnog kanala.',
+ errorKickNotAllowed: 'Pogreška: Nemate dopuštenja za progon korisnika %s.',
+ errorCommandNotAllowed: 'Pogreška: Naredba nije dopuštena: %s',
+ errorUnknownCommand: 'Pogreška: Nepoznata naredba: %s',
+ errorMaxMessageRate: 'Pogreška: Premašili ste najveći dopušteni broj poruka u minuti.',
+ errorConnectionTimeout: 'Pogreška: Neaktivna veza. Pokušajte ponovo.',
+ errorConnectionStatus: 'Pogreška: Stanje veze: %s',
+ errorSoundIO: 'Pogreška: Učitavanje datoteke zvuka nije uspjelo (Flash IO pogreška).',
+ errorSocketIO: 'Pogreška: Povezivanje s priključkom poslužitelja nije uspjelo (Flash IO pogreška).',
+ errorSocketSecurity: 'Pogreška: Povezivanje s priključkom poslužitelja nije uspjelo (Flash sigurnosna pogreška).',
+ errorDOMSyntax: 'Pogreška: Nepravilna DOM sintaksa (DOM ID: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/hu.js b/library/ajaxchat/chat/js/lang/hu.js
new file mode 100644
index 000000000..ec2a45e14
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/hu.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s belépett a chatre.',
+ logout: '%s kilépett a chatről.',
+ logoutTimeout: '%s kilépett a chatről (Időtúllépés).',
+ logoutIP: '%s kilépett a chatről (Hamis IP cím).',
+ logoutKicked: '%s ki lett rúgva a chatről.',
+ channelEnter: '%s belépett a szobába.',
+ channelLeave: '%s kilépett a szobából.',
+ privmsg: '(suttog)',
+ privmsgto: '(suttog %s felhasználónak)',
+ invite: '%s meghívott a következő szobába: %s.',
+ inviteto: 'A meghívása %s részére a(z) %s szobába elküldve.',
+ uninvite: '%s hívatlan vendégnek tart a(z) %s szobában.',
+ uninviteto: 'Hívatlan vendég jelzője %s számára elküldve a(z) %s szobában.',
+ queryOpen: 'Privát szoba megnyitva %s felhasználónak.',
+ queryClose: 'Privát szoba bezárva %s felhasználóval.',
+ ignoreAdded: '%s hozzáadva a figyelmen kívül hagyottakhoz.',
+ ignoreRemoved: '%s eltávolítva a figyelmen kívül hagyottak közül.',
+ ignoreList: 'Figyelmen kívül hagyott felhasználók:',
+ ignoreListEmpty: 'Nincsenek figyelmen kívül hagyott felhasználók.',
+ who: 'Jelenlévők:',
+ whoChannel: 'Jelenlévők a(z) %s szobában:',
+ whoEmpty: 'Senki nincs a megadott szobában.',
+ list: 'Szobák:',
+ bans: 'Kitiltott felhasználók:',
+ bansEmpty: 'Nincs kitiltott felhasználó.',
+ unban: '%s tiltása törölve.',
+ whois: '%s IP címe:',
+ whereis: '%s a következő szobákban van: %s.',
+ roll: '%s rolls %s and gets %s.',
+ nick: '%s új nickje %s.',
+ toggleUserMenu: '%s - felhasználói menüjének mutatása',
+ userMenuLogout: 'Kilépés',
+ userMenuWho: 'Jelenlévők listája',
+ userMenuList: 'Szobák listája',
+ userMenuAction: 'Akció küldése',
+ userMenuRoll: 'Dobókocka játék',
+ userMenuNick: 'Nick cseréje',
+ userMenuEnterPrivateRoom: 'Privát szobába lépés',
+ userMenuSendPrivateMessage: 'Privát üzenet küldése',
+ userMenuDescribe: 'Privát akció küldése',
+ userMenuOpenPrivateChannel: 'Privát szoba nyitása',
+ userMenuClosePrivateChannel: 'Privát szoba bezárása',
+ userMenuInvite: 'Meghívás',
+ userMenuUninvite: 'Hívatlan vendég',
+ userMenuIgnore: 'Figyelmen kívül hagy/engedélyez',
+ userMenuIgnoreList: 'Figyelmen kívül hagyottak',
+ userMenuWhereis: 'Szobák mutatása, ahol jelen van',
+ userMenuKick: 'Kirúgás/kitiltás',
+ userMenuBans: 'Kitiltottak listája',
+ userMenuWhois: 'IP megjelenítése',
+ unbanUser: '%s kitiltásának feloldása',
+ joinChannel: 'Belépés a szobába %s',
+ cite: '%s azt mondja:',
+ urlDialog: 'Kérem írja be a honlap URL-jét:',
+ deleteMessage: 'Chat üzenet törlése',
+ deleteMessageConfirm: 'Valóban törölni akarja az üzenetet?',
+ errorCookiesRequired: 'A cookiek engedélyezése szükséges a chat használatához.',
+ errorUserNameNotFound: 'Hiba: A %s felhasználó nem található.',
+ errorMissingText: 'Hiba: hiányzó üzenet.',
+ errorMissingUserName: 'Hiba: hiányzó felhasználónév.',
+ errorInvalidUserName: 'Hiba: hamis felhasználónév.',
+ errorUserNameInUse: 'Hiba: a név már használatban van.',
+ errorMissingChannelName: 'Hiba: hiányzó szoba név.',
+ errorInvalidChannelName: 'Hiba: hamis szoba név: %s',
+ errorPrivateMessageNotAllowed: 'Hiba: a privát üzenetek nem engedélyezettek.',
+ errorInviteNotAllowed: 'Hiba: nem vagy jogosult felhasználókat meghívni a szobába.',
+ errorUninviteNotAllowed: 'Hiba: nem vagy jogosult hívatlan vendégnek titulálni bárkit a szobában.',
+ errorNoOpenQuery: 'Hiba: nincs jogod szobát nyitni.',
+ errorKickNotAllowed: 'Hiba: nincs jogod kirúgni %s-t.',
+ errorCommandNotAllowed: 'Hiba: a parancs nem engedélyezett: %s',
+ errorUnknownCommand: 'Hiba: ismeretlen parancs: %s',
+ errorMaxMessageRate: 'Hiba: elérted a percenként küldhető maximális üzenet számot.',
+ errorConnectionTimeout: 'Hiba: időtúllépés! Próbáld újra!.',
+ errorConnectionStatus: 'Hiba: a kapcsolat állapota: %s',
+ errorSoundIO: 'Hiba: a hangfájl betöltése sikertelen. (I/O)',
+ errorSocketIO: 'Hiba: kapcsolódás a socket szerverhez sikertelen. (I/O)',
+ errorSocketSecurity: 'Hiba: kapcsolódás a socket szerverhez sikertelen. (Biztonsági hiba!)',
+ errorDOMSyntax: 'Hiba: Hibás DOM szintaxis (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/in.js b/library/ajaxchat/chat/js/lang/in.js
new file mode 100644
index 000000000..582b9703b
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/in.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s masuk ke chat.',
+ logout: '%s keluar dari chat.',
+ logoutTimeout: '%s telah keluar dari saluran (Timeout).',
+ logoutIP: '%s elah keluar dari saluran (Invalid IP address).',
+ logoutKicked: '%s elah keluar dari saluran (Kicked).',
+ channelEnter: '%s masuk saluran.',
+ channelLeave: '%s meninggalkan.',
+ privmsg: '(berbisik)',
+ privmsgto: '(berbisik ke %s)',
+ invite: '%s mengundang anda untuk gabung ke %s.',
+ inviteto: 'Undangan anda ke %s untuk gabung saluran %s telah dikirim.',
+ uninvite: '%s membatalkan untuk mengundang anda dari saluran %s.',
+ uninviteto: 'Pembatalan undangan anda ke %s untuk salura %s telah dikirim.',
+ queryOpen: 'Saluran Privasi telah dibuka untuk %s.',
+ queryClose: 'Saluran Privasi untuk %s telah ditutup.',
+ ignoreAdded: 'Menambah %s ke daftar yang diacuhkan.',
+ ignoreRemoved: 'Mencabut %s dari daftar yang diacuhkan.',
+ ignoreList: 'Acuhkan pengguna:',
+ ignoreListEmpty: 'Tidak ada nama dalam daftar yang diacuhkan.',
+ who: 'Pengguna online:',
+ whoChannel: 'Pengguna-2 yang online di saluran %s:',
+ whoEmpty: 'Tidak ada pengguna yang online di saluran tersebut.',
+ list: 'Saluran yang tersedia:',
+ bans: 'Pengguna yang diblok:',
+ bansEmpty: 'Tidak ada pengguna yang diblok.',
+ unban: 'Pembatalan Blok pengguna %s .',
+ whois: 'Alamat IP Pengguna %s :',
+ whereis: 'Pengguna %s ada di saluran %s.',
+ roll: '%s melempar %s dan mendapatkan %s.',
+ nick: '%s sekarang dikenal sebagai %s.',
+ toggleUserMenu: 'Tombol menu pengguna untuk %s',
+ userMenuLogout: 'Keluar',
+ userMenuWho: 'Daftar pengguna yang online',
+ userMenuList: 'Daftar saluran-saluran yang tersedia',
+ userMenuAction: 'Menjelaskan tindakan',
+ userMenuRoll: 'Melempar Dadu',
+ userMenuNick: 'Mengganti Nama',
+ userMenuEnterPrivateRoom: 'Memasuki ruang privasi',
+ userMenuSendPrivateMessage: 'Kirim pesan pribadi',
+ userMenuDescribe: 'Kirim tindakan pribadi',
+ userMenuOpenPrivateChannel: 'Buka Saluran Privasi',
+ userMenuClosePrivateChannel: 'Tutup Saluran Privasi',
+ userMenuInvite: 'Mengundang',
+ userMenuUninvite: 'Tidak Mengundang',
+ userMenuIgnore: 'Acuhkan/Terima',
+ userMenuIgnoreList: 'Daftar Pengguna yang diacuhkan',
+ userMenuWhereis: 'Tampilkan Saluran',
+ userMenuKick: 'Tendang/Blok',
+ userMenuBans: 'Daftar Pengguna yang diblok',
+ userMenuWhois: 'Tampilkan IP',
+ unbanUser: 'Batalkan blok pengguna %s',
+ joinChannel: 'Gabung Saluran %s',
+ cite: '%s berkata:',
+ urlDialog: 'Mohon masukan alamat (URL) of the web:',
+ deleteMessage: 'Hapus pesan chat ini',
+ deleteMessageConfirm: 'Yakin akan menghapus pesan chat yang dipilih?',
+ errorCookiesRequired: 'Cookies diperlukan untuk chat.',
+ errorUserNameNotFound: 'Error: Pengguna %s tidak ada.',
+ errorMissingText: 'Error: Teks pesan tidak ada.',
+ errorMissingUserName: 'Error: Nama tidak ada.',
+ errorInvalidUserName: 'Error: Kesalahan pada Nama.',
+ errorUserNameInUse: 'Error: Nama telah dipakai.',
+ errorMissingChannelName: 'Error: Nama saluran belum ada.',
+ errorInvalidChannelName: 'Error: Kesalahan pada nama saluran: %s',
+ errorPrivateMessageNotAllowed: 'Error: Pesan pribadi tidak diijinkan.',
+ errorInviteNotAllowed: 'Error: Anda tidak diijinkan untuk mengundang orang lain ke saluran ini.',
+ errorUninviteNotAllowed: 'Error: Anda tidak diijinkan untuk tidak mengundang seseorang ke saluran ini.',
+ errorNoOpenQuery: 'Error: Tidak ada saluran privasi yang dibuka.',
+ errorKickNotAllowed: 'Error: Anda tidak diijinkan untuk menendang %s.',
+ errorCommandNotAllowed: 'Error: Perintah tidak diijinkan: %s',
+ errorUnknownCommand: 'Error: Perintah tidak diketahui: %s',
+ errorMaxMessageRate: 'Error: Anda telah melampaui batas pesan maksimum per menitnya.',
+ errorConnectionTimeout: 'Error: Koneksi putus. Mohon dicoba kembali.',
+ errorConnectionStatus: 'Error: Status koneksi: %s',
+ errorSoundIO: 'Error: Gagal mengeluarkan suara (Flash IO Error).',
+ errorSocketIO: 'Error: Gagal mengadakan koneksi ke server (Flash IO Error).',
+ errorSocketSecurity: 'Error: Gagal mengadakan koneksi ke server (Flash Security Error).',
+ errorDOMSyntax: 'Error: Sintaks DOM yang tidak dikenal(DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/index.html b/library/ajaxchat/chat/js/lang/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/index.html
diff --git a/library/ajaxchat/chat/js/lang/it.js b/library/ajaxchat/chat/js/lang/it.js
new file mode 100644
index 000000000..a84c47ff9
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/it.js
@@ -0,0 +1,93 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author s8s8
+ * @author Massimiliano Tiraboschi
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s entra in Chat.',
+ logout: '%s esce dalla Chat.',
+ logoutTimeout: '%s esce (TimeOut).',
+ logoutIP: '%s esce (IP non valido).',
+ logoutKicked: '%s esce (Kicked).',
+ channelEnter: '%s entra nel canale.',
+ channelLeave: '%s lascia il canale.',
+ privmsg: '(privato)',
+ privmsgto: '(privato a %s)',
+ invite: '%s ti invita a entrare in %s.',
+ inviteto: 'Il tuo invito ad entrare nel canale %s è stato inviato a %s.',
+ uninvite: '%s ha rimosso il tuo invito per %s.',
+ uninviteto: 'Rimosso invito per %s per il canale %s.',
+ queryOpen: 'Canale privato aperto con %s.',
+ queryClose: 'Canale privato con %s chiuso.',
+ ignoreAdded: '%s aggiunto agli ingorati.',
+ ignoreRemoved: '%s rimosso dagli ignorati.',
+ ignoreList: 'Utenti Ignorati:',
+ ignoreListEmpty: 'Utenti permessi.',
+ who: 'Utenti Online:',
+ whoChannel: 'Utenti Online nel canale %s:',
+ whoEmpty: 'Nessun utente in linea nel canale.',
+ list: 'Canali disponibili:',
+ bans: 'Utenti Bannati:',
+ bansEmpty: 'Nessun utente bannato in lista.',
+ unban: 'Ban di %s rimosso.',
+ whois: '%s - IP:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s lancia %s e fa %s.',
+ nick: '%s è conosciuto ora come %s.',
+ toggleUserMenu: 'Mostra/Nascondi menu per %s',
+ userMenuLogout: 'Esci',
+ userMenuWho: 'Lista utenti online',
+ userMenuList: 'Lista canali disponibili',
+ userMenuAction: 'Descrivi azione',
+ userMenuRoll: 'Getta dadi',
+ userMenuNick: 'Cambia username',
+ userMenuEnterPrivateRoom: 'Entra canale privato',
+ userMenuSendPrivateMessage: 'Invia messaggio privato',
+ userMenuDescribe: 'Invia azione privata',
+ userMenuOpenPrivateChannel: 'Apri canale privato',
+ userMenuClosePrivateChannel: 'Chiudi canale privato',
+ userMenuInvite: 'Invita',
+ userMenuUninvite: 'Disinvita',
+ userMenuIgnore: 'Ignora/Accetta',
+ userMenuIgnoreList: 'Lista utenti ignorati',
+ userMenuWhereis: 'Mostra canale',
+ userMenuKick: 'Butta fuori/Banna',
+ userMenuBans: 'Lista utenti bannati',
+ userMenuWhois: 'Mostra IP',
+ unbanUser: 'Revoca il ban per l\'utente %s',
+ joinChannel: 'Entra nel canale %s',
+ cite: '%s dice:',
+ urlDialog: 'Inserire indirizzo (URL) della pagina Web:',
+ deleteMessage: 'Cancella questo messaggio',
+ deleteMessageConfirm: 'Sicuro di cancellare il messaggio selezionato ?',
+ errorCookiesRequired: 'I Cookies sono richiesti per questa chat.',
+ errorUserNameNotFound: 'Errore: Utente %s non trovato.',
+ errorMissingText: 'Errore: Messaggio di testo non trovato.',
+ errorMissingUserName: 'Errore: Nome Utente non trovato.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Errore: Canale non trovato.',
+ errorInvalidChannelName: 'Errore: Nome canale non valido: %s',
+ errorPrivateMessageNotAllowed: 'Errore: Messaggi privati non permessi.',
+ errorInviteNotAllowed: 'Errore: Non hai il permesso di invitare in questo canale.',
+ errorUninviteNotAllowed: 'Errore: Non hai il permesso di rimuovere inviti per queso canale.',
+ errorNoOpenQuery: 'Errore: Nessun canale privato aperto.',
+ errorKickNotAllowed: 'Errore: Non sei abilitato a Kikkare %s.',
+ errorCommandNotAllowed: 'Errore: Comando non permesso: %s',
+ errorUnknownCommand: 'Errore: Comando sconosciuto: %s',
+ errorMaxMessageRate: 'Errore: Hai superato il numero massimo di messaggi per minuto.',
+ errorConnectionTimeout: 'Errore: Connessione persa. Riprovare.',
+ errorConnectionStatus: 'Errore: Stato di Connessione: %s',
+ errorSoundIO: 'Errore: Caricamento files suono fallito (Flash IO Error).',
+ errorSocketIO: 'Errore: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/ja.js b/library/ajaxchat/chat/js/lang/ja.js
new file mode 100644
index 000000000..5d87d2eea
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ja.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s さんがログインしました',
+ logout: '%s さんがログアウトしました',
+ logoutTimeout: '%s さんが強制的にログアウトされました (タイムアウト)',
+ logoutIP: '%s さんが強制的にログアウトされました (不正な IPアドレス)',
+ logoutKicked: '%s さんが強制的にログアウトされました (キック).',
+ channelEnter: '%s さんが入室しました',
+ channelLeave: '%s さんが退室しました',
+ privmsg: '(プライベートメッセージ)',
+ privmsgto: '(%s さんへプライベートメッセージ)',
+ invite: '%s さんから チャンネル %s への招待 が届いています',
+ inviteto: '%s さんへ チャンネル %s への招待 を送りました',
+ uninvite: '%s さんから チャンネル %s への招待 を取り消されました',
+ uninviteto: '%s さんの チャンネル %s への招待 を取り消しました',
+ queryOpen: '二人きりモードを %s さんと開始しました',
+ queryClose: '%s さんとの二人きりモードを終了しました',
+ ignoreAdded: '%s さんを無視ユーザーリストに追加しました',
+ ignoreRemoved: '%s さんを無理ユーザーリストから削除しました',
+ ignoreList: '無視ユーザーリスト :',
+ ignoreListEmpty: 'あなたはどのユーザーも無視していません',
+ who: 'オンラインユーザー :',
+ whoChannel: 'チャンネル %s に入室中のユーザー :',
+ whoEmpty: 'そのチャンネルに入室中のユーザーは一人もいません',
+ list: '入室可能なチャンネル :',
+ bans: 'アクセス禁止ユーザーリスト :',
+ bansEmpty: 'アクセス禁止されたユーザーは一人もいません',
+ unban: 'ユーザー %s のアクセス禁止を取り消しました',
+ whois: 'ユーザー %s の IPアドレス :',
+ whereis: 'ユーザー %s はチャンネル %s にいます',
+ roll: '%s さんがサイコロを振りました。 %s - 結果 %s',
+ nick: '%s さんのニックネームは以降 %s です',
+ toggleUserMenu: '%s さんのユーザーメニューを表示する/表示しない',
+ userMenuLogout: 'ログアウト',
+ userMenuWho: 'オンラインユーザーリスト',
+ userMenuList: '入室可能なチャンネルのリスト',
+ userMenuAction: '感情を表現する',
+ userMenuRoll: 'サイコロを振る',
+ userMenuNick: 'ニックネーム',
+ userMenuEnterPrivateRoom: 'プライベートルームへ移動する',
+ userMenuSendPrivateMessage: 'プライベートメッセージを送る',
+ userMenuDescribe: '感情を表現する',
+ userMenuOpenPrivateChannel: '二人きりモードを開始する',
+ userMenuClosePrivateChannel: '二人きりモードを終了する',
+ userMenuInvite: '招待する',
+ userMenuUninvite: '招待を取り消す',
+ userMenuIgnore: '無視する/無視しない',
+ userMenuIgnoreList: '無視ユーザーリスト',
+ userMenuWhereis: 'ユーザーの居場所',
+ userMenuKick: 'キック/アクセス禁止',
+ userMenuBans: 'アクセス禁止ユーザーリスト',
+ userMenuWhois: 'IPアドレス',
+ unbanUser: 'ユーザー %s のアクセス禁止を取り消す',
+ joinChannel: 'チャンネル %s へ移動する',
+ cite: '%s さんが言いました :',
+ urlDialog: 'サイトのアドレス (URL) を入力してください :',
+ deleteMessage: 'このチャットメッセージを削除する',
+ deleteMessageConfirm: 'チャットメッセージを本当に削除してもよろしいですか?',
+ errorCookiesRequired: 'このチャットシステムを利用するには Cookie を有効にしておく必要があります',
+ errorUserNameNotFound: 'エラー : ユーザー %s が見つかりませんでした',
+ errorMissingText: 'エラー : メッセージが未入力です',
+ errorMissingUserName: 'エラー : ユーザー名が未入力です',
+ errorInvalidUserName: 'エラー : ユーザー名が正しくありません',
+ errorUserNameInUse: 'エラー : そのユーザー名は既に使われています',
+ errorMissingChannelName: 'エラー : チャンネル名が未入力です',
+ errorInvalidChannelName: 'エラー : チャンネル名が正しくありません : %s',
+ errorPrivateMessageNotAllowed: 'エラー : プライベートメッセージが許可されていません',
+ errorInviteNotAllowed: 'エラー : あなたはこのチャンネルで誰かを招待することを許可されていません',
+ errorUninviteNotAllowed: 'エラー : あなたはこのチャンネルで誰かの招待を取り消すことを許可されていません',
+ errorNoOpenQuery: 'エラー : 二人きりモードが開始されていません',
+ errorKickNotAllowed: 'エラー : あなたは %s さんをキックすることを許可されていません',
+ errorCommandNotAllowed: 'エラー : コマンドが許可されていません : %s',
+ errorUnknownCommand: 'エラー : コマンドが不正です : %s',
+ errorMaxMessageRate: 'エラー : 1分あたりに発言できる最大文字数を超えています',
+ errorConnectionTimeout: 'エラー : 接続がタイムアウトしました。再度試してください。',
+ errorConnectionStatus: 'エラー : 接続ステータス : %s',
+ errorSoundIO: 'エラー : サウンドファイルの読み込みに失敗しました (Flash IO Error)',
+ errorSocketIO: 'エラー : ソケットサーバへの接続に失敗しました (Flash IO Error)',
+ errorSocketSecurity: 'エラー : ソケットサーバへの接続に失敗しました (Flash Security Error)',
+ errorDOMSyntax: 'エラー : DOM の文法が不正です (DOM ID: %s)'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/ka.js b/library/ajaxchat/chat/js/lang/ka.js
new file mode 100644
index 000000000..6f0a24d72
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ka.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s ჩატში შემოვიდა.',
+ logout: '%s ჩატიდან გავიდა.',
+ logoutTimeout: '%s ჩატი დატოვა (დრო ამოიწურა).',
+ logoutIP: '%s ჩატი დატოვა (არასწორი IP მისამართი).',
+ logoutKicked: '%s ჩატი დატოვა (ამოარტყეს).',
+ channelEnter: '%s უერთდება არხს.',
+ channelLeave: '%s ტოვებს არხს.',
+ privmsg: '(ჩურჩულებს)',
+ privmsgto: '(%s-ს უჩურჩულებს)',
+ invite: '%s გეპაიჟებათ შეუერთდეთ %s-ს.',
+ inviteto: '%s-თვის შექმნილი მოსაწვევი, რათა შეუერთდეს არხ %s-ს, გაგზავნილია.',
+ uninvite: '%s თავის დაპატიჟებას არხ %s-თვის აუქმებს.',
+ uninviteto: '%s-თვის დაწერილი, %s არხის მოსაწვევის გაუქმება გაგხავნილია.',
+ queryOpen: 'პირადი არხი %s-სთან გასხნილია.',
+ queryClose: 'პირადი არხი %s-სთან დახურულია.',
+ ignoreAdded: '%s იგნორირების სიას დაემატა.',
+ ignoreRemoved: '%s იგნორირების სიიდან ამოღებულია.',
+ ignoreList: 'იგნორირებულები:',
+ ignoreListEmpty: 'იგნორირებული წევრები არაა.',
+ who: 'ხაზზე არიან:',
+ whoChannel: 'არხ %s-ში ხაზზე არიან:',
+ whoEmpty: 'მოცემულ არხში ხაზზე არავინაა.',
+ list: 'ხელმისაწვდომი არხები:',
+ bans: 'დაბლოკილი წევრები:',
+ bansEmpty: 'დაბლოკილი წევრები არაა.',
+ unban: '%s წევრის ბლოკი მოხსნილია.',
+ whois: '%s წევრის - IP მისამართი:',
+ whereis: 'წევრი %s იმყოფება %s არხში.',
+ roll: '%s აგდებს %s-ს და იღებს %s-ს.',
+ nick: '%s ახლა ცნობილია როგორც %s.',
+ toggleUserMenu: 'წევრის მენიუს %s-თვის ჩართვა/გათიშვა',
+ userMenuLogout: 'გასვლა',
+ userMenuWho: 'ჩამოწერე ხაზზე ვინაა',
+ userMenuList: 'ჩამოწერე ხელმისაწვდომი არხები',
+ userMenuAction: 'აღწერე ქმედება',
+ userMenuRoll: 'კამათლების გაგორება',
+ userMenuNick: 'მეტსახელის შეცვლა',
+ userMenuEnterPrivateRoom: 'პირად ოთახში შესვლა',
+ userMenuSendPrivateMessage: 'პირადი მიმოწერა',
+ userMenuDescribe: 'პირადი ქმედების გაგზავნა',
+ userMenuOpenPrivateChannel: 'გახსენი პირადი არხი',
+ userMenuClosePrivateChannel: 'დახურე პირადი არხი',
+ userMenuInvite: 'დაპატიჟება',
+ userMenuUninvite: 'დაპატიჟების გაუქმება',
+ userMenuIgnore: 'იგნორირება/მიღება',
+ userMenuIgnoreList: 'ჩამოწერე იგნორირებულები',
+ userMenuWhereis: 'მაჩვენე არხი',
+ userMenuKick: 'ამორტყმა/დაბლოკვა',
+ userMenuBans: 'დაბლოკილების ჩამოწერა',
+ userMenuWhois: 'IP-ს ჩვენება',
+ unbanUser: '%s წევრის ბლოკის მოხსნა',
+ joinChannel: '%s არხში შესვლა',
+ cite: '%s თქვა:',
+ urlDialog: 'გთხოვთ შეიყვანოთ ვებ-გვერდის მისამართი (URL):',
+ deleteMessage: 'გზავნილის წაშლა',
+ deleteMessageConfirm: 'მართლა წავშალოთ ეს გზავნილი?',
+ errorCookiesRequired: 'ჩატისთვის cookies არიან საჭირო.',
+ errorUserNameNotFound: 'შეცდომა: წევრი %s არ მოიძებნა.',
+ errorMissingText: 'შეცდომა: გზავნილის ტექსტი აკლია.',
+ errorMissingUserName: 'შეცდომა: აკლია მეტსახელი.',
+ errorInvalidUserName: 'შეცდომა: არასწორი მეტსახელი.',
+ errorUserNameInUse: 'შეცდომა: მეტსახელი დაკავებულია.',
+ errorMissingChannelName: 'შეცდომა: აკლია არხის სახელი.',
+ errorInvalidChannelName: 'შეცდომა: არხის სახელი - %s - არასწორია',
+ errorPrivateMessageNotAllowed: 'შეცდომა: პირადი მიმოწერა აკრზალულია.',
+ errorInviteNotAllowed: 'შეცდომა: უფლება არ გაქვთ მიმდინარე არხში ვინმე მოიწვიოთ.',
+ errorUninviteNotAllowed: 'შეცდომა: უფლება არ გაქავთ მინდინარე არხიდან ვინმესი გაგდება.',
+ errorNoOpenQuery: 'შეცდომა: პირადი არხები გახსნილი არაა.',
+ errorKickNotAllowed: 'შეცდომა: უფლება არ გაგჩნიათ %s-ს ამოარტყათ.',
+ errorCommandNotAllowed: 'შეცდომა: ბრზანება - %s - აკრძალულია',
+ errorUnknownCommand: 'შეცდომა: ბრძანება - %s - უცნობია',
+ errorMaxMessageRate: 'შეცდომა: თქვენ მიაღწიეთ წუთში მაქსიმალურ შესაძლებელ გზავნილების რიცხვს.',
+ errorConnectionTimeout: 'შეცდომა: კავშირს ვადა გაუვიდა. გთხოვთ, კიდევ სცადეთ.',
+ errorConnectionStatus: 'შეცდომა: კავშირის სტატუსი: %s',
+ errorSoundIO: 'შეცდომა: ხმის ფაილი ვერ ჩაიტვირთა (Flash IO Error).',
+ errorSocketIO: 'შეცდომა: სერვერის სოკეტთან დაკავშირება ჩაიშალა (Flash IO Error).',
+ errorSocketSecurity: 'შეცდომა: სერვერის სოკეტთან დაკავშირება ჩაიშალა (Flash Security Error).',
+ errorDOMSyntax: 'შეცდომა: არასწორი DOM სინტაქსი (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/kr.js b/library/ajaxchat/chat/js/lang/kr.js
new file mode 100644
index 000000000..27ef9196d
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/kr.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s께서 접속하였습니다.',
+ logout: '%s님께서 접속을 종료하였습니다.',
+ logoutTimeout: '%s님께서 시간초과로 나가셨습니다.',
+ logoutIP: '%s님께서 IP주소문제로 나가셨습니다.',
+ logoutKicked: '%s님께서 추방되었습니다.',
+ channelEnter: '%s님께서 들어오셨습니다.',
+ channelLeave: '%s님께서 나가셨습니다.',
+ privmsg: '(귓속말)',
+ privmsgto: '(%s에게 귓속말)',
+ invite: '%s님께서 %s채널에서 초대하셨습니다.',
+ inviteto: '%s을 %s채널로 초대하는 메시지를 보냈습니다..',
+ uninvite: '%s님께서 %s채널로의 초대를 취소하였습니다.',
+ uninviteto: '%s님께 %s채널로의 초대를 취소하는 메시지를 보냈습니다',
+ queryOpen: '%s님의 개인채널이 열렸습니다.',
+ queryClose: '%s님의 개인채널이 닫혔습니다.',
+ ignoreAdded: '%s님을 대화차단 목록에 추가하였습니다.',
+ ignoreRemoved: '%s님을 대화차단 목록에서 삭제하였습니다.',
+ ignoreList: '차단된 사용자:',
+ ignoreListEmpty: '차단된 사용자가 없습니다.',
+ who: '접속중인 사용자:',
+ whoChannel: '%s채널에 접속중인 사용자:',
+ whoEmpty: '해당 채널에 접속중인 사용자가 없습니다.',
+ list: '사용가능한 채널:',
+ bans: '추방된 사용자:',
+ bansEmpty: '추방된 사용자가 없습니다.',
+ unban: '%s을 다시 복구하였습니다.',
+ whois: '%s - IP주소:',
+ whereis: '%s님은 %s 채널에 계십니다.',
+ roll: '%s 롤 %s 및 도착 %s.',
+ nick: '%s님의 닉네임은 %s입니다.',
+ toggleUserMenu: '에 대한 전환 사용자 메뉴 %s',
+ userMenuLogout: '로그아웃',
+ userMenuWho: '접속중인 사용자',
+ userMenuList: '채널목록',
+ userMenuAction: '작업을 설명',
+ userMenuRoll: '주사위',
+ userMenuNick: '대화명 변경',
+ userMenuEnterPrivateRoom: '개인 대화방 입장',
+ userMenuSendPrivateMessage: '귓속말 전송',
+ userMenuDescribe: '개인 작업을 보내기',
+ userMenuOpenPrivateChannel: '개인 채널 개설',
+ userMenuClosePrivateChannel: '개인 채널 닫기',
+ userMenuInvite: '초대',
+ userMenuUninvite: '초대 취소',
+ userMenuIgnore: '차단/수락',
+ userMenuIgnoreList: '대화차단 목록',
+ userMenuWhereis: '채널확인',
+ userMenuKick: '추방',
+ userMenuBans: '추방된 사용자 목록',
+ userMenuWhois: '접속주소 확인',
+ unbanUser: '%s 사용자를 추방취소',
+ joinChannel: '%s 채널에 접속',
+ cite: '%s님의 말:',
+ urlDialog: '웹페이지의 주소를 입력하세요:',
+ deleteMessage: '이 메시지 삭제',
+ deleteMessageConfirm: '선택한 메시지를 삭제하시겠습니까?',
+ errorCookiesRequired: '쿠키 사용으로 설정하세요.',
+ errorUserNameNotFound: '오류: %s님을 찾을 수 없습니다.',
+ errorMissingText: '오류: 메시지를 찾을 수 없습니다.',
+ errorMissingUserName: '오류: 대화명을 찾을 수 없습니다.',
+ errorInvalidUserName: '오류: 잘못된 대화명입니다.',
+ errorUserNameInUse: '오류: 이미 사용중인 대화명입니다.',
+ errorMissingChannelName: '오류: 채널명을 찾을 수 없습니다.',
+ errorInvalidChannelName: '오류: %s 채널이 없습니다.',
+ errorPrivateMessageNotAllowed: '오류: 귓속말을 사용할 수 없습니다.',
+ errorInviteNotAllowed: '오류: 이 채널로 다른 사용자를 초대하는 권한이 없습니다.',
+ errorUninviteNotAllowed: '오류: 다른 사용자의 초대를 취소할 권한이 없습니다.',
+ errorNoOpenQuery: '오류: 열려있는 개인 채널이 없습니다..',
+ errorKickNotAllowed: '오류: %s를 추방할 수 있는 권한이 없습니다.',
+ errorCommandNotAllowed: '오류: %s 명령을 사용할 수 없습니다.',
+ errorUnknownCommand: '오류: %s은 없는 명령어입니다.',
+ errorMaxMessageRate: '오류: 1분동안 연속해서 입력할 수 있는 메시지 수를 초과하였습니다.',
+ errorConnectionTimeout: '오류: 접속시간을 초과하였습니다.',
+ errorConnectionStatus: '오류: 접속 상태: %s',
+ errorSoundIO: '오류: 입출력 실패로 소리파일을 불러오는데 실패하였습니다.',
+ errorSocketIO: '오류: 입출력 실패로 서버에 접속하는데 실패하였습니다.',
+ errorSocketSecurity: '오류: 보안문제로 서버에 접속하는데 실패하였습니다.',
+ errorDOMSyntax: '오류: DOM 문법이 잘못되었습니다. (DOM ID: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/mk.js b/library/ajaxchat/chat/js/lang/mk.js
new file mode 100644
index 000000000..8ca441112
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/mk.js
@@ -0,0 +1,9 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Nebojsa Ilijoski
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+var ajaxChatLang={login:"%s се приклучи на четот.",logout:"%s излезе од четот.",logoutTimeout:"%s излезе автоматски од четот (Истече времето).",logoutIP:"%s излезе автоматски од четот (Погрешна IP адреса).",logoutKicked:"%s излезе автоматски од четот (Злоупотреба).",channelEnter:"%s се прилкучи на каналот.",channelLeave:"%s го напушти канала.",privmsg:"(шепоти)",privmsgto:"(шепоти на %s)",invite:"%s ве кани да се приклучите со него %s.",inviteto:"Поканата за %s да се приклучи на каналот %s беше испратена.",uninvite:"%s е отпоканет на поканата за каналот %s.",uninviteto:"Отпоканата на поканата до %s за каналот %s беше испратена.",queryOpen:"Отворен е приватен канал за %s.",queryClose:"Затворен е приватен канал за %s.",ignoreAdded:"%s е ставен на списокот на игнорирани.",ignoreRemoved:"%s беше отстранет од списокот на игнорирани.",ignoreList:"Игнорирани корисници:",ignoreListEmpty:"Нема игнорирани корисници.",who:"Оnline корисници:",whoChannel:"Online корисници на каналот %s:",whoEmpty:"На дадениот канал нема online корисници.",list:"Приватни канали:",bans:"Блокирани корисници:",bansEmpty:"Нема блокирани корисници.",unban:"Блокирањето на корисникот %s е завршено.",whois:"Корисникот %s — IP адреса:",whereis:"Корисникот %s е на канал %s.",roll:"%s фрли %s и доби %s.",nick:"%s веќе се нарекува %s.",toggleUserMenu:"Прикажување/скривање на корисничкото мени за %s",userMenuLogout:"Излези",userMenuWho:"Online корисници",userMenuList:"Приватни канали",userMenuAction:"Опис на дејство",userMenuRoll:"Фрлање на коцка",userMenuNick:"Промена на името",userMenuEnterPrivateRoom:"Влез во приватна соба",userMenuSendPrivateMessage:"Испраќање на приватна порака",userMenuDescribe:"Испраќање на приватно дејство",userMenuOpenPrivateChannel:"Отварање на приватен канал",userMenuClosePrivateChannel:"Затварање на приватен канал",userMenuInvite:"Покана",userMenuUninvite:"Одговор на покана",userMenuIgnore:"Одбивање/прифаќање",userMenuIgnoreList:"Игнорирани корисници",userMenuWhereis:"Преглед на канал",userMenuKick:"Прифаќање/Блокирање",userMenuBans:"Блокирани корисници",userMenuWhois:"Преглед на IP адреса",unbanUser:"Одблокирање на %s",joinChannel:"Присоединување кон каналот %s",cite:"%s рече:",urlDialog:"Ве молам, внесете адреса (URL) на страницата:",deleteMessage:"Бришење на пораката",deleteMessageConfirm:"Дали сте сигурни дека сакате да е избришете пораката?",errorCookiesRequired:"За четот е потребно да се активни cookies.",errorUserNameNotFound:"Грешка: Корисникот %s не е пронајден.",errorMissingText:"Грешка: Недостасува текст од пораката.",errorMissingUserName:"Грешка: Недостасува корисничкото име.",errorInvalidUserName:"Грешка: Погрешно корисничко име.",errorUserNameInUse:"Грешка: Корисничкото име веќе е во употреба.",errorMissingChannelName:"Грешка: Недостасува името на каналот.",errorInvalidChannelName:"Грешка: Името на каналот не е валидно: %s",errorPrivateMessageNotAllowed:"Грешка: Лични пораки не се дозволени.",errorInviteNotAllowed:"Грешка: Не ви е позволено да каните корисници на овој канал.",errorUninviteNotAllowed:"Грешка: Не ви е дозволено да отпоканување на овој канал.",errorNoOpenQuery:"Грешка: Не е отворен приватен канал.",errorKickNotAllowed:"Грешка: Не ви е дозволено да исфрлате %s.",errorCommandNotAllowed:"Грешка: Командата не е дозволена: %s",errorUnknownCommand:"Грешка: Непозната команда: %s",errorMaxMessageRate:"Грешка: Го надминавте максималниот број пораки во минута.",errorConnectionTimeout:"Грешка: Истече на времето на врската. Ве молам обидете се повторно!",errorConnectionStatus:"Грешка: Состојба на врската: %s",errorSoundIO:"Грешка: Неуспешно поставување на звукот (Влезно-излезна грешка на Флешот).",errorSocketIO:"Грешка: Неуспешна врска кон сокетниот сервер (Влезно-излезна грешка на Флешот).",errorSocketSecurity:"Грешка: Неуспешна врска кон сокетниот сервер (Грешка во сигурноста на Флашот).",errorDOMSyntax:"Грешка: Погрешна синтакса на DOM (DOM ID: %s)."}; \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/nl-be.js b/library/ajaxchat/chat/js/lang/nl-be.js
new file mode 100644
index 000000000..4184ce7c9
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/nl-be.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Nic Mertens
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s komt in het chatkanaal.',
+ logout: '%s verlaat het chatkanaal.',
+ logoutTimeout: '%s verlaat het chatkanaal (Timeout).',
+ logoutIP: '%s is afgemeld (Ongeldig IP address).',
+ logoutKicked: '%s is afgemeld (Kick door admin of moderator).',
+ channelEnter: '%s komt het kanaal binnen.',
+ channelLeave: '%s verlaat het kanaal.',
+ privmsg: '(fluistert)',
+ privmsgto: '(fluistert naar %s)',
+ invite: '%s nodigt je uit om naar %s te komen.',
+ inviteto: 'Je uitnodiging naar %s om het kanaal %s te bezoeken, werd verstuurd.',
+ uninvite: '%s annuleert de uitnodiging van kanaal %s.',
+ uninviteto: 'De annulatie van je uitnodiging aan %s voor het kanaal %s werd verstuurd.',
+ queryOpen: 'Privékanaal geopend naar %s.',
+ queryClose: 'Privékanaal naar %s wordt gesloten.',
+ ignoreAdded: '%s is toegevoegd aan de negeer lijst.',
+ ignoreRemoved: '%s werd verwijderd van de negeerlijst.',
+ ignoreList: 'Genegeerde gebruikers:',
+ ignoreListEmpty: 'Er zijn geen genegeerde gebruikers.',
+ who: 'Online gebruikers:',
+ whoChannel: 'Online gebruikers in channel %s:',
+ whoEmpty: 'Er zijn geen gebruikers in het gekozen kanaal.',
+ list: 'Beschikbare kanalen:',
+ bans: 'Gebande gebruikers:',
+ bansEmpty: 'Er zijn geen gebande gebruikers.',
+ unban: 'Ban van gebruiker %s opgeheven.',
+ whois: 'Gebruiker %s - IP adres:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s smijt %s en krijgt %s.',
+ nick: '%s heet nu %s.',
+ toggleUserMenu: 'Open menu voor gebruiker %s',
+ userMenuLogout: 'Afmelden',
+ userMenuWho: 'Lijst online gebruikers',
+ userMenuList: 'Lijst beschikbaare kanalen',
+ userMenuAction: 'Beschrijf actie',
+ userMenuRoll: 'Rol dobbelsteen',
+ userMenuNick: 'Wijzig gebruikersnaam',
+ userMenuEnterPrivateRoom: 'Ga privékanaal binnen',
+ userMenuSendPrivateMessage: 'Stuur privé bericht',
+ userMenuDescribe: 'Stuur privé actie',
+ userMenuOpenPrivateChannel: 'Open privé kanaal',
+ userMenuClosePrivateChannel: 'Sluit privé kanaal',
+ userMenuInvite: 'Nodig uit',
+ userMenuUninvite: 'Uitnodiging intrekken',
+ userMenuIgnore: 'Negeren/aanvaarden',
+ userMenuIgnoreList: 'Lijst genegeerde gebruikers',
+ userMenuWhereis: 'Toon kanaal',
+ userMenuKick: 'Verwijderen/Verbannen',
+ userMenuBans: 'Lijst verbande gebruikers',
+ userMenuWhois: 'Toon IP',
+ unbanUser: 'Gebande gebruiker %s terug toelaten',
+ joinChannel: 'Betreedt kanaal %s',
+ cite: '%s zei:',
+ urlDialog: 'Gelieve het (URL) adres van de webpagina in te geven:',
+ deleteMessage: 'Verwijder dit chat bericht',
+ deleteMessageConfirm: 'Bent u zeker dat u dit bericht wil verwijderen?',
+ errorCookiesRequired: 'Cookies moeten aangeschakeld zijn voor deze chat.',
+ errorUserNameNotFound: 'Fout: Gebruiker %s werd niet gevonden.',
+ errorMissingText: 'Fout: Ontbrekende berichttekst.',
+ errorMissingUserName: 'Fout: Ontbrekende Gebruikersnaam.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Gebruikersnaam wordt al gebruikt',
+ errorMissingChannelName: 'Fout: Ontbrekende kanaalnaam.',
+ errorInvalidChannelName: 'Fout: Ongeldige kanaalnaam: %s',
+ errorPrivateMessageNotAllowed: 'Error: Private berichten zijn niet toegestaan.',
+ errorInviteNotAllowed: 'Fout: Je bent niet geautoriseerd om iemand uit te nodigen naar dit kanaal.',
+ errorUninviteNotAllowed: 'Fout: Je bent niet geautoriseerd om een uitnodiging naar iemand te annuleren op dit kanaal.',
+ errorNoOpenQuery: 'Fout: Er is geen privékanaal geopend.',
+ errorKickNotAllowed: 'Fout: Je ben niet geautoriseerd om %s te kicken.',
+ errorCommandNotAllowed: 'Fout: Opdracht is niet toegestaan: %s',
+ errorUnknownCommand: 'Fout: Onbekende opdracht: %s',
+ errorMaxMessageRate: 'Error: Je hebt de limiet voor het aantal berichten per minuut overschreven.',
+ errorConnectionTimeout: 'Fout: Connection timeout. Gelieve opnieuw te proberen.',
+ errorConnectionStatus: 'Fout: Verbindingsstatus: %s',
+ errorSoundIO: 'Error: Geluidsbestand kon niet geladen worden (Flash IO Error).',
+ errorSocketIO: 'Error: Verbinding met Socket server is verloren (Flash IO Error).',
+ errorSocketSecurity: 'Error: Verbinding met Socket server is verloren (Flash Security Error).',
+ errorDOMSyntax: 'Error: Ongeldige DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/nl.js b/library/ajaxchat/chat/js/lang/nl.js
new file mode 100644
index 000000000..179d0e703
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/nl.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Dutch localisation: Patrick Donker
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s betreedt het chatkanaal.',
+ logout: '%s verlaat het chatkanaal.',
+ logoutTimeout: '%s verlaat het chatkanaal (Timeout).',
+ logoutIP: '%s is afgemeld (Ongeldig IP address).',
+ logoutKicked: '%s is afgemeld (Verbannen door admin of moderator).',
+ channelEnter: '%s betreedt het kanaal.',
+ channelLeave: '%s verlaat het kanaal.',
+ privmsg: '(fluistert)',
+ privmsgto: '(fluistert naar %s)',
+ invite: '%s nodigt je uit om naar %s te komen.',
+ inviteto: 'Je uitnodiging naar %s om het kanaal %s te bezoeken, is verzonden.',
+ uninvite: '%s annuleert de uitnodiging van kanaal %s.',
+ uninviteto: 'De annulering van je uitnodiging aan %s voor het kanaal %s is verzonden.',
+ queryOpen: 'Privékanaal geopend voor %s.',
+ queryClose: 'Privékanaal naar %s wordt gesloten.',
+ ignoreAdded: '%s is toegevoegd aan de negeer lijst.',
+ ignoreRemoved: '%s is verwijderd van de negeerlijst.',
+ ignoreList: 'Genegeerde gebruikers:',
+ ignoreListEmpty: 'Er zijn geen genegeerde gebruikers.',
+ who: 'Aanwezige gebruikers:',
+ whoChannel: 'aanwezige gebruikers in channel %s:',
+ whoEmpty: 'Het gekozen kanaal is leeg.',
+ list: 'Beschikbare kanalen:',
+ bans: 'Verbannen gebruikers:',
+ bansEmpty: 'Er zijn geen gebruikers verbannen.',
+ unban: 'Ban van gebruiker %s opgeheven.',
+ whois: 'Gebruiker %s - IP adres:',
+ whereis: 'Gebruiker %s is in kanaal %s.',
+ roll: '%s gooit %s en krijgt %s.',
+ nick: '%s heet nu %s.',
+ toggleUserMenu: 'Open gebuikersmenu %s',
+ userMenuLogout: 'Afmelden',
+ userMenuWho: 'Lijst aanwezige gebruikers',
+ userMenuList: 'Lijst beschikbare kanalen',
+ userMenuAction: 'Beschrijf actie',
+ userMenuRoll: 'Rol dobbelsteen',
+ userMenuNick: 'Wijzig gebruikersnaam',
+ userMenuEnterPrivateRoom: 'Betreed privékanaal',
+ userMenuSendPrivateMessage: 'Stuur privé bericht',
+ userMenuDescribe: 'Stuur privé actie',
+ userMenuOpenPrivateChannel: 'Open privé kanaal',
+ userMenuClosePrivateChannel: 'Sluit privé kanaal',
+ userMenuInvite: 'Nodig uit',
+ userMenuUninvite: 'Uitnodiging intrekken',
+ userMenuIgnore: 'Negeren/aanvaarden',
+ userMenuIgnoreList: 'Lijst genegeerde gebruikers',
+ userMenuWhereis: 'Toon kanaal',
+ userMenuKick: 'Verwijderen/Verbannen',
+ userMenuBans: 'Lijst verbannen gebruikers',
+ userMenuWhois: 'Toon IP adres',
+ unbanUser: 'Verbannen gebruiker %s weer toelaten',
+ joinChannel: 'Betreed kanaal %s',
+ cite: '%s zei:',
+ urlDialog: 'Geef het adres (URL) van de webpagina op:',
+ deleteMessage: 'Verwijder dit bericht',
+ deleteMessageConfirm: 'Weet u zeker dat u dit bericht wilt verwijderen?',
+ errorCookiesRequired: 'Cookies moeten ingeschakeld zijn voor deze chat.',
+ errorUserNameNotFound: 'Fout: Gebruiker %s is niet gevonden.',
+ errorMissingText: 'Fout: Ontbrekende berichttekst.',
+ errorMissingUserName: 'Fout: Ontbrekende gebruikersnaam.',
+ errorInvalidUserName: 'Error: Ongeldige gebruikersnaam.',
+ errorUserNameInUse: 'Error: Gebruikersnaam is in gebruik.',
+ errorMissingChannelName: 'Fout: Ontbrekende kanaalnaam.',
+ errorInvalidChannelName: 'Fout: Ongeldige kanaalnaam: %s',
+ errorPrivateMessageNotAllowed: 'Fout: Privéberichten zijn niet toegestaan.',
+ errorInviteNotAllowed: 'Fout: U bent niet geautoriseerd uitnodigingen te versturen voor dit kanaal.',
+ errorUninviteNotAllowed: 'Fout: U bent niet geautoriseerd uitnodigingen te annuleren voor dit kanaal.',
+ errorNoOpenQuery: 'Fout: Geen privékanaal beschikbaar.',
+ errorKickNotAllowed: 'Fout: U ben niet geautoriseerd om %s te verbannen.',
+ errorCommandNotAllowed: 'Fout: Opdracht niet toegestaan: %s',
+ errorUnknownCommand: 'Fout: Onbekende opdracht: %s',
+ errorMaxMessageRate: 'Error: U hebt het maximaal aantal berichten per minuut bereikt.',
+ errorConnectionTimeout: 'Fout: Connection timeout. Probeer opnieuw.',
+ errorConnectionStatus: 'Fout: Verbindingsstatus: %s',
+ errorSoundIO: 'Error: Geluidsbestand kan worden geladen (Flash IO Error).',
+ errorSocketIO: 'Error: Verbinding met Socket server is verbroken (Flash IO Error).',
+ errorSocketSecurity: 'Error: Verbinding met Socket server is verbroken (Flash Security Error).',
+ errorDOMSyntax: 'Error: Ongeldige DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/no.js b/library/ajaxchat/chat/js/lang/no.js
new file mode 100644
index 000000000..4a9a5ac3f
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/no.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author DagArneKirkerod
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s logger inn på Chat.',
+ logout: '%s logger ut av Chat.',
+ logoutTimeout: '%s har blitt utlogget (Tidsbegrensning).',
+ logoutIP: '%s har blitt logget ut (Ugyldig IP Adresse).',
+ logoutKicked: '%s har blitt logget ut (sparket ut).',
+ channelEnter: '%s kommer inn på kanalen.',
+ channelLeave: '%s forlater kanalen.',
+ privmsg: '(hviskere)',
+ privmsgto: '(hvisker til %s)',
+ invite: '%s inviterer deg til å delta %s.',
+ inviteto: 'Din invitasjon til %s å delta på kanal %s er sendt.',
+ uninvite: '%s trekker din invitasjon fra kanal %s.',
+ uninviteto: 'Din tilbaketrekkning av invitasjon til %s for kanal %s er sendt.',
+ queryOpen: 'Privat kanal åpnet til %s.',
+ queryClose: 'Privat kanal til %s er stengt.',
+ ignoreAdded: 'Lagt %s til listen over ignorerte brukere.',
+ ignoreRemoved: 'Fjernet %s fra liste over ignorerte brukere.',
+ ignoreList: 'Ignorerte Brukere:',
+ ignoreListEmpty: 'Ingen ignorerte brukere på lista.',
+ who: 'Påloggede Brukere:',
+ whoChannel: 'Online Brukere i kanal %s:',
+ whoEmpty: 'Ingen påloggede brukere på valgt kanal.',
+ list: 'Tilgjenglige kanaler:',
+ bans: 'Utsparkede Brukere:',
+ bansEmpty: 'Ingen utsparkede brukere på lista.',
+ unban: 'Bruker %s fjernet fra liste over utsparkede brukere.',
+ whois: 'Bruker %s - IP adresse:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s triller %s og får %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Endre brukernavn',
+ userMenuEnterPrivateRoom: 'Skriv privat rom',
+ userMenuSendPrivateMessage: 'Send en privat melding',
+ userMenuDescribe: 'Send privat handling',
+ userMenuOpenPrivateChannel: 'Åpne privat kanal',
+ userMenuClosePrivateChannel: 'Lukk privat kanal',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'Liste med ignorerte brukere',
+ userMenuWhereis: 'Vise kanal',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'Liste sperrede brukere',
+ userMenuWhois: 'Vise IP',
+ unbanUser: 'Tilbakekalle forbud av brukeren %s',
+ joinChannel: 'Delta på kanal %s',
+ cite: '%s sa:',
+ urlDialog: 'Skriv inn adressen (URL) på web siden:',
+ deleteMessage: 'Slett denne chat-melding',
+ deleteMessageConfirm: 'Vil du virkelig slette den valgte chat-melding?',
+ errorCookiesRequired: 'Cookies er påkrevet på denne chatten.',
+ errorUserNameNotFound: 'Feil: Bruker %s ble ikke funnet.',
+ errorMissingText: 'Feil: Mangler meldingstekst.',
+ errorMissingUserName: 'Feil: Mangler Brukernavn.',
+ errorInvalidUserName: 'Feil: Ugyldig brukernavn.',
+ errorUserNameInUse: 'Feil: Brukernavnet er allerede i bruk.',
+ errorMissingChannelName: 'Feil: Mangler navn på kanal.',
+ errorInvalidChannelName: 'Feil: Feil navn på kanal: %s',
+ errorPrivateMessageNotAllowed: 'Feil: Private meldinger ikke tillatt.',
+ errorInviteNotAllowed: 'Feil: Du har ikke lov til å invitere noen til denne kanalen.',
+ errorUninviteNotAllowed: 'Feil: Du har ikke lov til å fjerne invitasjon til noen brukere på denne kanalen.',
+ errorNoOpenQuery: 'Feil: Ingen private kanaler er åpne.',
+ errorKickNotAllowed: 'Feil: Du har ikke lov til å sparke ut %s.',
+ errorCommandNotAllowed: 'Feil: Kommando ikke tillatt: %s',
+ errorUnknownCommand: 'Feil: Ukjent kommando: %s',
+ errorMaxMessageRate: 'Feil: Du overskredet maksimalt antall meldinger per minutt.',
+ errorConnectionTimeout: 'Feil: Oppkoblingstid utgått. Forsøk forsøk igjen.',
+ errorConnectionStatus: 'Feil: Oppkoblingsstatus: %s',
+ errorSoundIO: 'Feil: Kunne ikke laste lydfil (Flash IO Error).',
+ errorSocketIO: 'Feil: Tilkobling til stikkontakt server mislyktes (Flash IO Error).',
+ errorSocketSecurity: 'Feil: Tilkobling til stikkontakt server mislyktes (Flash Security Error).',
+ errorDOMSyntax: 'Feil: Ugyldig DOM Syntaks (DOM ID: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/pl.js b/library/ajaxchat/chat/js/lang/pl.js
new file mode 100644
index 000000000..3353d1bdd
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/pl.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Tomasz Topa, http://tomasz.topa.pl/
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s wszedł na czat.',
+ logout: '%s wyszedł na czat.',
+ logoutTimeout: '%s został rozłączony (Przekroczony czas połączenia).',
+ logoutIP: '%s został rozłączony (Nieprawidłowy adres IP).',
+ logoutKicked: '%s został wyrzucony.',
+ channelEnter: '%s wszedł do pokoju.',
+ channelLeave: '%s wyszedł z pokoju.',
+ privmsg: '(szept)',
+ privmsgto: '(szept do %s)',
+ invite: '%s zaprasza Cię do pokoju %s.',
+ inviteto: 'Twoje zaprosznie dla %s do wejścia do pokoju %s zostało wysłane.',
+ uninvite: '%s cofa zaproszenie do pokoju %s.',
+ uninviteto: 'Twoje zaproszenie dla %s do wejścia do pokoju %s zostało wycofane.',
+ queryOpen: 'Prywatna rozmowa z %s rozpoczęta.',
+ queryClose: 'Prywatna rozmowa z %s zakończona.',
+ ignoreAdded: '%s dodany do listy ignorowanych.',
+ ignoreRemoved: '%s usunięty z listy ignorowanych.',
+ ignoreList: 'Ignorowani użytkownicy:',
+ ignoreListEmpty: 'Brak ignorowanych użytkowników.',
+ who: 'Użytkownicy online:',
+ whoChannel: 'Użytkownicy online w pokoju %s:',
+ whoEmpty: 'W wybranym pokoju nikogo obecnie nie ma.',
+ list: 'Dostępne pokoje:',
+ bans: 'Zablokowani użytkownicy:',
+ bansEmpty: 'Brak zablokowanych użytkowników',
+ unban: 'Blokada dla %s zdjęta.',
+ whois: 'Adres IP użytkownika %s:',
+ whereis: 'Użytkownik %s jest w pokoju %s.',
+ roll: '%s rzuca kostką %s i uzyskuje wynik(i): %s.',
+ nick: '%s zmienia nick na %s.',
+ toggleUserMenu: 'Włącz/wyłącz menu użytkownika %s',
+ userMenuLogout: 'Wyloguj',
+ userMenuWho: 'Użytkownicy online',
+ userMenuList: 'Dostępne pokoje',
+ userMenuAction: 'Napisz co teraz robisz',
+ userMenuRoll: 'Rzuć kostką',
+ userMenuNick: 'Zmień nick',
+ userMenuEnterPrivateRoom: 'Wejdź do prywatnego pokoju',
+ userMenuSendPrivateMessage: 'Wyślij prywatną wiadomość',
+ userMenuDescribe: 'Napisz prywatnie co teraz robisz',
+ userMenuOpenPrivateChannel: 'Rozpocznij prywatną rozmowę',
+ userMenuClosePrivateChannel: 'Zakończ prywatną rozmowę',
+ userMenuInvite: 'Zaproś',
+ userMenuUninvite: 'Wycofaj zaproszenie',
+ userMenuIgnore: 'Ignoruj/akceptuj',
+ userMenuIgnoreList: 'Lista ignorowanych użytkowników',
+ userMenuWhereis: 'Pokaż pokój',
+ userMenuKick: 'Wyrzuć/Zablokuj',
+ userMenuBans: 'Lista zablokowanych użytkowników',
+ userMenuWhois: 'Pokaż IP',
+ unbanUser: 'Zdejmij blokadę dla użytkownika %s',
+ joinChannel: 'Wejdź do pokoju %s',
+ cite: '%s powiedział:',
+ urlDialog: 'Podaj adres (URL) strony:',
+ deleteMessage: 'Usuń tę wiadomość',
+ deleteMessageConfirm: 'Na pewno usunać tę wiadomość?',
+ errorCookiesRequired: 'Do poprawnego działania czat wymaga obsługi Cookies.',
+ errorUserNameNotFound: 'Błąd: Użytkownik %s nie został znaleziony.',
+ errorMissingText: 'Błąd: Nie wpisano tekstu.',
+ errorMissingUserName: 'Błąd: Nie wpisano nicka.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Błąd: Nie wpisano nazwy pokoju.',
+ errorInvalidChannelName: 'Błąd: Nieprawidłowa nazwa pokoju: %s',
+ errorPrivateMessageNotAllowed: 'Błąd: Prywatne wiadomości zostały zablokowane.',
+ errorInviteNotAllowed: 'Błąd: Nie możesz wysyłać zaproszeń do tego pokoju.',
+ errorUninviteNotAllowed: 'Błąd: Nie możesz cofać zaproszeń z tego pokoju.',
+ errorNoOpenQuery: 'Błąd: Brak prywatnych rozmów.',
+ errorKickNotAllowed: 'Błąd: Nie możesz wyrzucić użytkownika %s.',
+ errorCommandNotAllowed: 'Błąd: Nieprawidłowe polecenie: %s',
+ errorUnknownCommand: 'Błąd: Nieznane polecenie: %s',
+ errorMaxMessageRate: 'Błąd: Przekroczyłeś maksymalną liczbę wiadomości wysyłanych w ciągu minuty. Poczekaj chwilę...',
+ errorConnectionTimeout: 'Błąd: Czas połączenia przekroczony. Spróbuj ponownie.',
+ errorConnectionStatus: 'Błąd: Stan połączenia: %s',
+ errorSoundIO: 'Błąd: nie można pobrać pliku dźwiękowego (Flash IO Error).',
+ errorSocketIO: 'Bład: nie można połączyć się z serwerem (Flash IO Error).',
+ errorSocketSecurity: 'Błąd: Połączenie z serwerem nie powiodło się (Flash Security Error).',
+ errorDOMSyntax: 'Błąd: Nieprawidłowa składnia DOM (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/pt-br.js b/library/ajaxchat/chat/js/lang/pt-br.js
new file mode 100644
index 000000000..eebfce0df
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/pt-br.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author vitoalvaro
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s acaba de entrar no Chat.',
+ logout: '%s acaba de sair no Chat.',
+ logoutTimeout: '%s desconectou (Tempo esgotado).',
+ logoutIP: '%s desconectou (Endereço de IP inválido).',
+ logoutKicked: '%s desconectou (Expulso do canal).',
+ channelEnter: '%s entrou no canal.',
+ channelLeave: '%s saiu do canal.',
+ privmsg: '(sussurra)',
+ privmsgto: '(Sussurrar para %s)',
+ invite: '%s convida você para participar %s.',
+ inviteto: 'O seu convite para se juntar ao %s do canal %s foi enviado.',
+ uninvite: '%s desconvidou você do canal %s.',
+ uninviteto: 'Seu desconvidamento %s do canal %s foi enviada.',
+ queryOpen: 'Canal privado aberto para %s.',
+ queryClose: 'Canal privado para %s fechado.',
+ ignoreAdded: 'Adicionar %s para a lista do igrnorado.',
+ ignoreRemoved: 'Remover %s da lista do ignorado.',
+ ignoreList: 'Usuários ignorados:',
+ ignoreListEmpty: 'Nenhuma lista usuários ignorados.',
+ who: 'Usuários Online:',
+ whoChannel: 'Usuários online no canal %s:',
+ whoEmpty: 'Nenhum usuários online na determinado canal.',
+ list: 'Os canais disponíveis:',
+ bans: 'Usuários banidos:',
+ bansEmpty: 'Nenhuma lista usuários banidos.',
+ unban: 'Usuário de banido %s revogado.',
+ whois: 'Usuário %s - enderenço IP:',
+ whereis: 'Usuário %s está no canal %s.',
+ roll: '%s rolas %s e começa %s.',
+ nick: '%s é agora conhecido como %s.',
+ toggleUserMenu: 'Alternar usuário menu de %s',
+ userMenuLogout: 'Deslogar',
+ userMenuWho: 'Lista usuários online',
+ userMenuList: 'Lista os canais disponíveis',
+ userMenuAction: 'Descreva ação',
+ userMenuRoll: 'Jogar dados',
+ userMenuNick: 'Trocar usuário',
+ userMenuEnterPrivateRoom: 'Entrar sala privada',
+ userMenuSendPrivateMessage: 'Enviar mensagem privada',
+ userMenuDescribe: 'Enviar ação privada',
+ userMenuOpenPrivateChannel: 'Abrir canal privada',
+ userMenuClosePrivateChannel: 'Fechar canal privada',
+ userMenuInvite: 'Convidar',
+ userMenuUninvite: 'Desconvidar',
+ userMenuIgnore: 'Ignorar/Aceitar',
+ userMenuIgnoreList: 'Lista usuários banidos',
+ userMenuWhereis: 'Exibir canais',
+ userMenuKick: 'Kickar/Banir',
+ userMenuBans: 'Lista usuários banidos',
+ userMenuWhois: 'Exibir IP',
+ unbanUser: 'Revogar usuário de banido %s',
+ joinChannel: 'Entrar canal %s',
+ cite: '%s cita:',
+ urlDialog: 'Digite o endereço (URL) da página:',
+ deleteMessage: 'Excluir esta mensagem',
+ deleteMessageConfirm: 'Realmente apagar a mensagem selecionada chat?',
+ errorCookiesRequired: 'Os cookies são requeridas para este Chat.',
+ errorUserNameNotFound: 'Erro: Usuário %s não encontrado.',
+ errorMissingText: 'Erro: Faltando mensagem texto.',
+ errorMissingUserName: 'Erro: Usuário faltando.',
+ errorInvalidUserName: 'Erro: Usuário inválido.',
+ errorUserNameInUse: 'Erro: Usuário já em uso.',
+ errorMissingChannelName: 'Erro: Faltando nome do canal.',
+ errorInvalidChannelName: 'Erro: Inválido nome do canal: %s',
+ errorPrivateMessageNotAllowed: 'Erro: Mensagens privadas não são permitidos.',
+ errorInviteNotAllowed: 'Erro: Você não tem permissão para convidar alguém para este canal.',
+ errorUninviteNotAllowed: 'Erro: Você não está autorizado a desconvidar alguém deste canal.',
+ errorNoOpenQuery: 'Erro: Nenhum canal privado aberto.',
+ errorKickNotAllowed: 'Erro: Você não está autorizado a kickar %s.',
+ errorCommandNotAllowed: 'Erro: Comando não permitido: %s',
+ errorUnknownCommand: 'Erro: Comando desconhecido: %s',
+ errorMaxMessageRate: 'Erro: Você excedeu o número máximo de mensagens por minuto.',
+ errorConnectionTimeout: 'Erro: Intervalo de parada da conexão. Por favor, tente novamente..',
+ errorConnectionStatus: 'Erro: Status da conexão: %s',
+ errorSoundIO: 'Erro: Falha ao carregar som arquivo (Flash IO Error).',
+ errorSocketIO: 'Erro: Conexão para socket servidor falhou (Flash IO Error).',
+ errorSocketSecurity: 'Erro: Conexão para socket servidor falhou (Flash Security Error).',
+ errorDOMSyntax: 'Erro: Inválido DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/pt-pt.js b/library/ajaxchat/chat/js/lang/pt-pt.js
new file mode 100644
index 000000000..fd6a0cbd5
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/pt-pt.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author of translate Carlos Rocha (aka Broas@)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s acaba de entrar no chat.',
+ logout: '%s acaba de sair no chat.',
+ logoutTimeout: '%s desligou-se (Tempo esgotado).',
+ logoutIP: '%s desligou-se (Endereço de IP inválido).',
+ logoutKicked: '%s desligou-se (Expulso da sala).',
+ channelEnter: '%s entrou na sala.',
+ channelLeave: '%s saiu da sala.',
+ privmsg: '(Mensagem privada)',
+ privmsgto: '(Mensagem privada enviada para %s)',
+ invite: '%s convidou-te para entrar na sala %s.',
+ inviteto: 'O teu convite para %s se juntar à sala %s foi enviado.',
+ uninvite: '%s cancelou o convite para entrares na sala %s.',
+ uninviteto: 'O cancelamento do convite para %s entrar na sala %s foi enviado.',
+ queryOpen: 'Sala privada aberta para %s.',
+ queryClose: 'A sala privada para %s está fechada.',
+ ignoreAdded: 'Adicionaste %s à a lista do ignorados.',
+ ignoreRemoved: 'Removeste %s da lista de ignorados.',
+ ignoreList: 'Utilizadores ignorados:',
+ ignoreListEmpty: 'Ninguém está ignorado.',
+ who: 'Utilizadores online:',
+ whoChannel: 'Utilizadores online na sala %s:',
+ whoEmpty: 'Nenhum utilizador online na determinada sala.',
+ list: 'Salas disponíveis:',
+ bans: 'Utilizadores banidos:',
+ bansEmpty: 'Ninguém está banido.',
+ unban: 'O utilizador %s foi desbanido.',
+ whois: 'Endereço IP do utilizador %s:',
+ whereis: 'O utilizador %s está na sala %s.',
+ roll: '%s rola %s e começa com %s.',
+ nick: '%s mudou o nick para %s.',
+ toggleUserMenu: 'Menu de alternância de %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'Lista de utilizadores online',
+ userMenuList: 'Lista de salas disponíveis',
+ userMenuAction: 'Acção administrativa',
+ userMenuRoll: 'Jogar dados',
+ userMenuNick: 'Trocar de nick',
+ userMenuEnterPrivateRoom: 'Entrar na sala privada',
+ userMenuSendPrivateMessage: 'Enviar mensagem privada',
+ userMenuDescribe: 'Enviar acção administrativa em privado',
+ userMenuOpenPrivateChannel: 'Abrir sala privada',
+ userMenuClosePrivateChannel: 'Fechar sala privada',
+ userMenuInvite: 'Convidar',
+ userMenuUninvite: 'Cancelar convite',
+ userMenuIgnore: 'Recusar/Aceitar',
+ userMenuIgnoreList: 'Lista utilizadores ignorados',
+ userMenuWhereis: 'Mostrar salas',
+ userMenuKick: 'Kickar/Banir',
+ userMenuBans: 'Lista de utilizadores banidos',
+ userMenuWhois: 'Mostrar IP',
+ unbanUser: 'Desbanir %s',
+ joinChannel: 'Entrar na sala %s',
+ cite: '%s cita:',
+ urlDialog: 'Digita o endereço (URL) da página:',
+ deleteMessage: 'Eliminar esta mensagem',
+ deleteMessageConfirm: 'Tens a certeza que queres eliminar a mensagem selecionada do chat?',
+ errorCookiesRequired: 'Os cookies são requeridos para utilizar o chat.',
+ errorUserNameNotFound: 'Erro: O utilizador %s não foi encontrado.',
+ errorMissingText: 'Erro: Falta o texto.',
+ errorMissingUserName: 'Erro: Falta o utilizador.',
+ errorInvalidUserName: 'Erro: Utilizador inválido.',
+ errorUserNameInUse: 'Erro: Utilizador em uso.',
+ errorMissingChannelName: 'Erro: Falta o nome da sala.',
+ errorInvalidChannelName: 'Erro: O nome da sala é inválido: %s',
+ errorPrivateMessageNotAllowed: 'Erro: Não são premitidas mensagens privadas.',
+ errorInviteNotAllowed: 'Erro: Não tens permissão para convidar alguém para uma sala.',
+ errorUninviteNotAllowed: 'Erro: Não estás autorizado a cancelar algum convite.',
+ errorNoOpenQuery: 'Erro: Nenhuma sala privada aberta.',
+ errorKickNotAllowed: 'Erro: Não tens permissão para kickar %s.',
+ errorCommandNotAllowed: 'Erro: O comando %s não é permitido.',
+ errorUnknownCommand: 'Erro: Comando desconhecido: %s',
+ errorMaxMessageRate: 'Erro: Excedeste o número máximo de mensagens permitidas por minuto.',
+ errorConnectionTimeout: 'Erro: O tempo de limite para a conexão esgotou. Por favor, tenta novamente..',
+ errorConnectionStatus: 'Erro: Estado da conexão: %s',
+ errorSoundIO: 'Erro: Falha ao carregar o ficheiro de som (Erro Flash IO).',
+ errorSocketIO: 'Erro: A conexão socket para o servidor falhou (Erro Flash IO).',
+ errorSocketSecurity: 'Erro: A conexão socket para o servidor falhou (Erro de segurança Flash).',
+ errorDOMSyntax: 'Erro: Síntese DOM inválida (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/ro.js b/library/ajaxchat/chat/js/lang/ro.js
new file mode 100644
index 000000000..7a03947aa
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ro.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author K.Z.
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s se autentifică pe Chat.',
+ logout: '%s iese de pe Chat.',
+ logoutTimeout: '%s a fost scos de pe Chat (Timeout).',
+ logoutIP: '%s a fost scos de pe Chat (Adresă IP incorectă).',
+ logoutKicked: '%s a fost scos de pe Chat (Dat afară).',
+ channelEnter: '%s se alătură canalului.',
+ channelLeave: '%s părăseşte canalul.',
+ privmsg: '(şopteşte)',
+ privmsgto: '(şopteşte lui %s)',
+ invite: '%s vă invită să vă alăturaţi %s.',
+ inviteto: 'Invitaţia trimisă de dumneavoastră către %s de a se alătura canalului %s a fost trimisă.',
+ uninvite: '%s vă cere să paraşiţi canalul %s.',
+ uninviteto: 'Cererea dumnevoastră către %s de a părăsi canalul %s a fost trimisă.',
+ queryOpen: 'Canal privat deschis către %s.',
+ queryClose: 'Canalul privat către %s s-a închis.',
+ ignoreAdded: 'Am adăugat utilizatorul %s la lista de utilizatori ignoraţi.',
+ ignoreRemoved: 'Am şters utilizatorul %s din lista de utilizatori ignoraţi.',
+ ignoreList: 'Utilizatori ignoraţi:',
+ ignoreListEmpty: 'Nu a fost listat nici-un utilizator ignorat.',
+ who: 'Utilizatori activi:',
+ whoChannel: 'Online Users in channel %s:',
+ whoEmpty: 'Nici-un utilzator activ in canalul respectiv.',
+ list: 'Canale disponibile:',
+ bans: 'Utilizatori care au accesul interzis la chat:',
+ bansEmpty: 'Nu a fost listat nici-un utilizator care are accesul interzis.',
+ unban: 'Interzicerea accesului pentru utilizatorul %s a fost revocată.',
+ whois: 'Utilizatorul %s - adresă IP:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s aruncă %s si îi cade %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Change username',
+ userMenuEnterPrivateRoom: 'Enter private room',
+ userMenuSendPrivateMessage: 'Send private message',
+ userMenuDescribe: 'Send private action',
+ userMenuOpenPrivateChannel: 'Open private channel',
+ userMenuClosePrivateChannel: 'Close private channel',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'List ignored users',
+ userMenuWhereis: 'Display channel',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'List banned users',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'Alăturăte canalului %s',
+ cite: '%s a spus:',
+ urlDialog: 'Vă rugăm introduceţi adresa (URL) al paginii web:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'Aveţi nevoie de cookies activate pentru acest chat.',
+ errorUserNameNotFound: 'Eroare: Utilizatorul %s nu a fost găsit.',
+ errorMissingText: 'Eroare: Nu aţi introdus nici-un text.',
+ errorMissingUserName: 'Eroare: Nu aţi introdus nici-un nume de utilizator.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Eroare: Nu aţi introdus nici-un canal.',
+ errorInvalidChannelName: 'Eroare: Nume de canal incorect: %s',
+ errorPrivateMessageNotAllowed: 'Eroare: Mesajele private sunt interzise.',
+ errorInviteNotAllowed: 'Eroare: Nu aveţi voie să invitaţi pe nimeni pe acest canal.',
+ errorUninviteNotAllowed: 'Eroare: Nu aveţi voie sa cereţi cuiva de pe acest canal să părăsesca canalul.',
+ errorNoOpenQuery: 'Eroare: Nici-un canal privat deschis.',
+ errorKickNotAllowed: 'Eroare: Nu aveţi voie să dati afară pe %s.',
+ errorCommandNotAllowed: 'Eroare: Comanda interzisă: %s',
+ errorUnknownCommand: 'Eroare: Comanda necunoscută: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'Eroare: Connection timeout. Please try again.',
+ errorConnectionStatus: 'Eroare: Statusul conexiunii: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/ru.js b/library/ajaxchat/chat/js/lang/ru.js
new file mode 100644
index 000000000..847fdb82c
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/ru.js
@@ -0,0 +1,93 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author SkyKnight
+ * @author Dmitry Plyonkin
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s входит в чат.',
+ logout: '%s выходит из чата.',
+ logoutTimeout: '%s вышел из чата по таймоуту.',
+ logoutIP: '%s вышел из чата (неверный IP адрес).',
+ logoutKicked: '%s был вышвырнут из чата (Kicked).',
+ channelEnter: '%s присоединяется к каналу.',
+ channelLeave: '%s покидает канал.',
+ privmsg: '(приватное сообщение)',
+ privmsgto: '(приватное сообщение %s)',
+ invite: '%s приглашает Вас присоединиться к %s.',
+ inviteto: 'Ваше приглашение %s присоедениться к каналу %s было успешно отправлено.',
+ uninvite: '%s отзывает Ваше приглашение из канала %s.',
+ uninviteto: 'Вы отозвали приглашение пользователю %s для канала %s.',
+ queryOpen: 'Приватный канал открыт к %s.',
+ queryClose: 'Приватный канал к %s закрыт.',
+ ignoreAdded: '%s добавлен в игнорлист.',
+ ignoreRemoved: '%s удален из игнорлиста.',
+ ignoreList: 'Игнорируемые пользователи:',
+ ignoreListEmpty: 'Игнорируемых пользователей не найдено.',
+ who: 'Пользователи:',
+ whoChannel: 'Пользователи в канале %s:',
+ whoEmpty: 'В данном канале нет пользователей.',
+ list: 'Доступные каналы:',
+ bans: 'Забаненные пользователи:',
+ bansEmpty: 'Нет забаненных пользователей.',
+ unban: 'Пользователь %s разбанен.',
+ whois: 'Пользователь %s - IP адрес:',
+ whereis: 'Пользователь %s находится в канале %s.',
+ roll: '%s кинул кубики %s. Результат %s.',
+ nick: '%s сменил имя на %s.',
+ toggleUserMenu: 'Меню пользователя %s',
+ userMenuLogout: 'Выйти',
+ userMenuWho: 'Список пользователей',
+ userMenuList: 'Список каналов',
+ userMenuAction: 'Действие',
+ userMenuRoll: 'Бросить кубик',
+ userMenuNick: 'Сменить имя',
+ userMenuEnterPrivateRoom: 'Войти в комнату',
+ userMenuSendPrivateMessage: 'Отправить приватное сообщение',
+ userMenuDescribe: 'Приватное действие',
+ userMenuOpenPrivateChannel: 'Открыть приватный канал',
+ userMenuClosePrivateChannel: 'Закрыть приватный канал',
+ userMenuInvite: 'Пригласить',
+ userMenuUninvite: 'Отменить приглашение',
+ userMenuIgnore: 'Игнорировать/Принять',
+ userMenuIgnoreList: 'Список игнорируемых',
+ userMenuWhereis: 'В каком канале?',
+ userMenuKick: 'Выкинуть/Забанить',
+ userMenuBans: 'Список забаненных',
+ userMenuWhois: 'Показать IP',
+ unbanUser: 'Отменить бан пользователя %s',
+ joinChannel: ' %s присоединился к каналу',
+ cite: '%s сказал:',
+ urlDialog: 'Пожалуйста введите адрес (URL) Web-страницы:',
+ deleteMessage: 'Удалить сообщение',
+ deleteMessageConfirm: 'Вы действительно хотите удалить это сообщение?',
+ errorCookiesRequired: 'Необходимо включить Cookies.',
+ errorUserNameNotFound: 'Ошибка: Пользователь %s не найдет.',
+ errorMissingText: 'Ошибка: Отсутствует текст сообщения.',
+ errorMissingUserName: 'Ошибка: Отсутствует имя.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Ошибка: Отсутствует имя канала.',
+ errorInvalidChannelName: 'Ошибка: Не верное имя канала: %s',
+ errorPrivateMessageNotAllowed: 'Ошибка: Приватные сообщения не разрешены.',
+ errorInviteNotAllowed: 'Ошибка: У Вас нет прав приглашать кого-либо в этот канал.',
+ errorUninviteNotAllowed: 'Ошибка: У Вас нет прав отозвать приглашение из этого канала.',
+ errorNoOpenQuery: 'Ошибка: Приватный канал не открыт.',
+ errorKickNotAllowed: 'Ошибка: У Вас нет прав забанить %s.',
+ errorCommandNotAllowed: 'Ошибка: Команда недоступна: %s',
+ errorUnknownCommand: 'Ошибка: Неизвестная команда: %s',
+ errorMaxMessageRate: 'Ошибка: Вы превысили ограничение на количество сообщений, отправленных за минуту.',
+ errorConnectionTimeout: 'Ошибка: Соединение не установлено. Пожалуйста, попробуйте еще раз.',
+ errorConnectionStatus: 'Ошибка: Статус соединения: %s',
+ errorSoundIO: 'Ошибка: Не получается загрузить звуковой файл (Flash IO Error).',
+ errorSocketIO: 'Ошибка: Не удалось открыть сокет (Flash IO Error).',
+ errorSocketSecurity: 'Ошибка: Не удалость открыть сокет (Flash Security Error).',
+ errorDOMSyntax: 'Ошибка: Некорректный синтаксис DOM (DOM ID: %s).'
+
+}
diff --git a/library/ajaxchat/chat/js/lang/sk.js b/library/ajaxchat/chat/js/lang/sk.js
new file mode 100644
index 000000000..3b9b06945
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/sk.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Peter
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s sa prihlásil do chatu.',
+ logout: '%s sa odhlásil z chatu.',
+ logoutTimeout: '%s bol odhlásený pre neaktivitu.',
+ logoutIP: '%s bol odhlásený (nesprávna IP adresa).',
+ logoutKicked: '%s bol odhlásený (vylúčený).',
+ channelEnter: '%s vstúpil do kanálu.',
+ channelLeave: '%s opustil kanál.',
+ privmsg: '(súkromný hovor)',
+ privmsgto: '(súkromne hovorí s %s)',
+ invite: '%s vás pozýva na rozhovor %s.',
+ inviteto: 'Vaša pozvánka na rozhovor s %s v kanáli %s dola odoslaná.',
+ uninvite: '%s neprijal Vaše pozvanie z kanálu %s.',
+ uninviteto: 'Vaše pozvanie pre %s v kanáli %s bolo poslané.',
+ queryOpen: 'Súkromný kanál s %s otvorený.',
+ queryClose: 'Súkromný kanál s %s zatvorený.',
+ ignoreAdded: '%s je pridaný do zoznamu zamietnutých.',
+ ignoreRemoved: '%s je odstránený zo zoznamu zamietnutých.',
+ ignoreList: 'Zamietnutí užívatelia:',
+ ignoreListEmpty: 'Zoznam zamietnutých užívateľov je prázdny.',
+ who: 'Pripojení užívatelia:',
+ whoChannel: 'Online Users in channel %s:',
+ whoEmpty: 'Žiadni pripojení užívatelia na danom kanáli.',
+ list: 'Dostupné kanály:',
+ bans: 'Vylúčení užívatelia:',
+ bansEmpty: 'Zoznam vylúčených užívateľov je prázdny.',
+ unban: 'Vylúčenie užívateľa %s je zrušené.',
+ whois: 'Užívateľová %s - IP adresa:',
+ whereis: 'User %s is in channel %s.',
+ roll: '%s hodil %s a padlo mu číslo %s.',
+ nick: '%s is now known as %s.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Logout',
+ userMenuWho: 'List online users',
+ userMenuList: 'List available channels',
+ userMenuAction: 'Describe action',
+ userMenuRoll: 'Roll dice',
+ userMenuNick: 'Change username',
+ userMenuEnterPrivateRoom: 'Enter private room',
+ userMenuSendPrivateMessage: 'Send private message',
+ userMenuDescribe: 'Send private action',
+ userMenuOpenPrivateChannel: 'Open private channel',
+ userMenuClosePrivateChannel: 'Close private channel',
+ userMenuInvite: 'Invite',
+ userMenuUninvite: 'Uninvite',
+ userMenuIgnore: 'Ignore/Accept',
+ userMenuIgnoreList: 'List ignored users',
+ userMenuWhereis: 'Display channel',
+ userMenuKick: 'Kick/Ban',
+ userMenuBans: 'List banned users',
+ userMenuWhois: 'Display IP',
+ unbanUser: 'Revoke ban of user %s',
+ joinChannel: 'Pripojiť kanál %s',
+ cite: '%s povedal:',
+ urlDialog: 'Prosím, vložte adresu (URL) webstránky:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'Tento chat vyžaduje mať povolené Cookies.',
+ errorUserNameNotFound: 'Chyba: Užívateľ %s nenájdený.',
+ errorMissingText: 'Chyba: Chýba text správy.',
+ errorMissingUserName: 'Chyba: Chýba meno užívateľa.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Chyba: Chýba meno kanálu.',
+ errorInvalidChannelName: 'Chyba: Nesprávne meno kanálu: %s',
+ errorPrivateMessageNotAllowed: 'Chyba: Súkromné správy nie sú povolené.',
+ errorInviteNotAllowed: 'Chyba: Nemáte povolenie pozívať užívateľov do tohoto kanálu.',
+ errorUninviteNotAllowed: 'Chyba: Nemáte povolenie zamietnuť pozvanie užívateľov z tohoto kanálu.',
+ errorNoOpenQuery: 'Chyba: Súkromný kanál nie je otvorený.',
+ errorKickNotAllowed: 'Chyba: Nie ste oprávnený vylúčiť %s.',
+ errorCommandNotAllowed: 'Chyba: Príkaz nie je povolený: %s',
+ errorUnknownCommand: 'Chyba: Neznámy príkaz: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'Chyba: Vypršal časový limit pripojenia. Skúste prosím znovu.',
+ errorConnectionStatus: 'Chyba: Stav pripojenia: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/sl.js b/library/ajaxchat/chat/js/lang/sl.js
new file mode 100644
index 000000000..9b9b4b4ae
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/sl.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Valter Pepelkoˇ
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s prijavljen-a na Klepetu.',
+ logout: '%s odjavljen-a iz Klepeta.',
+ logoutTimeout: '%s je prijava potekla (Timeout).',
+ logoutIP: '%s je prijava potekla (Nepopolna IP adresa).',
+ logoutKicked: '%s je prijava potekla (Kicked).',
+ channelEnter: '%s je vstopil-a v sobo.',
+ channelLeave: '%s odšel-a iz sobe.',
+ privmsg: '(privatno sporoÄŤilo)',
+ privmsgto: '(se privatno pogovarja z %s)',
+ invite: '%s vas vabi na razgovor v %s.',
+ inviteto: 'Vaše vabilo za razgovor z %s v sobi %s je poslano.',
+ uninvite: '%s se ne želi odzvati vašemu vabilu v sobi %s.',
+ uninviteto: 'Vaš preklic vabila za %s v sobi %s je poslano.',
+ queryOpen: 'Privatna soba za %s je odprta.',
+ queryClose: 'Privatna soba za %s je zaprta.',
+ ignoreAdded: '%s je dodan na seznam ignoriranih.',
+ ignoreRemoved: '%s je odstranjen iz seznama ignoriranih.',
+ ignoreList: 'Ignorirani uporabniki:',
+ ignoreListEmpty: 'Seznam ignoriranih uporabnikov je prazen.',
+ who: 'Prisotni:',
+ whoChannel: 'Prisotni v sobi %s:',
+ whoEmpty: 'V tej sobi ni uporabnikov.',
+ list: 'Dostopne sobe:',
+ bans: 'Uporabniki s prepovedjo dostopa:',
+ bansEmpty: 'Seznam uporabnikov s prepovedjo dostopa je prazen.',
+ unban: 'Prepoved dostopa uporabniku je preklicana.',
+ whois: 'Uporabnik %s - IP adresa:',
+ whereis: 'Uporabnik %s je v sobi %s.',
+ roll: '%s je vrgel %s Rezultat je: %s.',
+ nick: '%s sedaj uporablja nick %s.',
+ toggleUserMenu: 'Preklopi uporabniški meni za %s',
+ userMenuLogout: 'Odjava',
+ userMenuWho: 'Seznam prisotnih uporabnikov',
+ userMenuList: 'Seznam dostopnih sob',
+ userMenuAction: 'Opiši akcijo',
+ userMenuRoll: 'Vrzi kocko',
+ userMenuNick: 'Zamenjaj uporabniško ime',
+ userMenuEnterPrivateRoom: 'Vstopi v privatno sobo',
+ userMenuSendPrivateMessage: 'Pošlji privatno sporočilo',
+ userMenuDescribe: 'Pošlji privatno akcijo',
+ userMenuOpenPrivateChannel: 'Odpri privatno sobo',
+ userMenuClosePrivateChannel: 'Zapri privatno sobo',
+ userMenuInvite: 'Poklicati',
+ userMenuUninvite: 'Preklicati',
+ userMenuIgnore: 'Ignoriraj/Sprejemi',
+ userMenuIgnoreList: 'Seznam ignoriranih uporabnikov',
+ userMenuWhereis: 'PrikaĹľi sobo',
+ userMenuKick: 'IzvrĹľeen/Prepovedan',
+ userMenuBans: 'Seznam prepovedanih uporabnikov',
+ userMenuWhois: 'PrikaĹľi IP adreso',
+ unbanUser: 'Preklicati prepoved uporabniku %s',
+ joinChannel: 'Vstopi v sobo %s',
+ cite: '%s pravi:',
+ urlDialog: 'Prosimo vas, vnesite naslov (URL) web strani:',
+ deleteMessage: 'Izbriši to sporočilo',
+ deleteMessageConfirm: 'Ali res izbrišem izbrano sporočilo?',
+ errorCookiesRequired: 'Pozor: uporaba piškotkov (cookies) je nujna za to klepetalnico!',
+ errorUserNameNotFound: 'Napaka: uporabnik %s ni najden!',
+ errorMissingText: 'Napaka: manjka besedilo sporoÄŤila!',
+ errorMissingUserName: 'Napaka: manjka uporabniško ime!',
+ errorInvalidUserName: 'Napaka: Nepravilno uporabniško ime!',
+ errorUserNameInUse: 'Napaka: uporabniško ime je že v uporabi!',
+ errorMissingChannelName: 'Napaka: ni imena sobe!',
+ errorInvalidChannelName: 'Napaka: napaÄŤno ime sobe: %s',
+ errorPrivateMessageNotAllowed: 'Napaka: privatna sporoÄŤila niso dovoljena!',
+ errorInviteNotAllowed: 'Napaka: Nimate dovoljenja, da lahko druge vabite v to sobo!',
+ errorUninviteNotAllowed: 'Napaka: Nimate dovoljenja, da lahko druge vrĹľete iz te sobe!',
+ errorNoOpenQuery: 'Napaka: Privatna soba ni odprta!',
+ errorKickNotAllowed: 'NApaka: Nimate dovoljenja, da lahko vrĹľete %s',
+ errorCommandNotAllowed: 'Napaka: Ukaz ni dozvoljen: %s',
+ errorUnknownCommand: 'Napaka: Neznan ukaz: %s',
+ errorMaxMessageRate: 'NApaka: Presegli ste največje dovoljeno število sporočil na minuto!.',
+ errorConnectionTimeout: 'Napaka: ÄŤas povezave se je iztekel. Poskusite znova!',
+ errorConnectionStatus: 'Napaka: Status povezave: %s',
+ errorSoundIO: 'Napaka: ZvoÄŤne datoteke ni bilo mogoÄŤe naloĹľiti (Napaka Flash IO)!',
+ errorSocketIO: 'Napaka: Povezava na server ni uspela (Napaka Flash IO)!',
+ errorSocketSecurity: 'Napaka: Povezava na server ni uspela (Napaka Flash Security)!',
+ errorDOMSyntax: 'Napaka: Nepopolna DOM Syntaxa (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/sr.js b/library/ajaxchat/chat/js/lang/sr.js
new file mode 100644
index 000000000..b5367b1e2
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/sr.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Saša Stojanović
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s prijavljen-a na Chat.',
+ logout: '%s odjavljen-a sa Chata.',
+ logoutTimeout: '%s je prijava istekla (Timeout).',
+ logoutIP: '%s je prijava istekla (Invalid IP address).',
+ logoutKicked: '%s je prijava istekla (Kicked).',
+ channelEnter: '%s je ušao-la u sobu.',
+ channelLeave: '%s izašao-la iz sobe.',
+ privmsg: '(privatna poruka)',
+ privmsgto: '(privatno razgovara sa %s)',
+ invite: '%s vas poziva na razgovor u %s.',
+ inviteto: 'Vaš poziv za razgovor sa %s u sobu %s je poslat.',
+ uninvite: '%s vam otkazuje pozivnicu u sobi %s.',
+ uninviteto: 'Vaše otkazivanje pozivnice za %s u sobi %s je poslato.',
+ queryOpen: 'Privatna soba za %s je otvorena.',
+ queryClose: 'Privatna soba za %s je zatvorena.',
+ ignoreAdded: '%s je dodat u listu ignorisanih.',
+ ignoreRemoved: '%s je uklonjen iz liste ignorisanih.',
+ ignoreList: 'Ignorisani korisnici:',
+ ignoreListEmpty: 'Lista ignorisanih korisnika je prazna.',
+ who: 'Prisutni korisnici:',
+ whoChannel: 'Prisutni korisnici u sobi %s:',
+ whoEmpty: 'Nema prisutnih korisnika u toj sobi.',
+ list: 'Dostupne sobe:',
+ bans: 'Zabranjeni korisnici:',
+ bansEmpty: 'Lista zabranjenih korisnika je prazna.',
+ unban: 'Zabrana korisnika %s je povučena.',
+ whois: 'Korisnik %s - IP adresa:',
+ whereis: 'Korisnik %s je u sobi %s.',
+ roll: '%s je bacio %s Rezultat %s.',
+ nick: '%s je sada poznat kao %s.',
+ toggleUserMenu: 'Preklopi korisnički meni za %s',
+ userMenuLogout: 'Odjavljivanje',
+ userMenuWho: 'Lista prisutnih korisnika',
+ userMenuList: 'Lista dostupnih soba',
+ userMenuAction: 'Opiši akciju',
+ userMenuRoll: 'Baci kocku',
+ userMenuNick: 'Promeni korisničko ime',
+ userMenuEnterPrivateRoom: 'Uđi u privatnu sobu',
+ userMenuSendPrivateMessage: 'Pošalji privatnu poruku',
+ userMenuDescribe: 'Pošalji privatnu akciju',
+ userMenuOpenPrivateChannel: 'Otvori privatnu sobu',
+ userMenuClosePrivateChannel: 'Zatvori privatnu sobu',
+ userMenuInvite: 'Pozvati',
+ userMenuUninvite: 'Opozvati',
+ userMenuIgnore: 'Ignorisati/Prihvatiti',
+ userMenuIgnoreList: 'Lista ignorisanih korisnika',
+ userMenuWhereis: 'Prikaži sobu',
+ userMenuKick: 'Izbačen/Zabranjen',
+ userMenuBans: 'Lista zabranjenih korisnika',
+ userMenuWhois: 'Prikaži IP',
+ unbanUser: 'Opozvati zabranu korisnika %s',
+ joinChannel: 'Pristupi sobi %s',
+ cite: '%s reče:',
+ urlDialog: 'Molimo vas, unesite adresu (URL) web stranice:',
+ deleteMessage: 'Delete this chat message',
+ deleteMessageConfirm: 'Really delete the selected chat message?',
+ errorCookiesRequired: 'Pažnja: kolačići su neophodni za ovaj Chat.',
+ errorUserNameNotFound: 'Greška: korisnik %s nije pronađen.',
+ errorMissingText: 'Greška: nedostaje tekst poruke.',
+ errorMissingUserName: 'Greška: nedostaje korisničko ime.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Greška: nedostaje ime sobe.',
+ errorInvalidChannelName: 'Greška: pogrešno ime sobe: %s',
+ errorPrivateMessageNotAllowed: 'Greška: privatne poruke nisu dozvoljene.',
+ errorInviteNotAllowed: 'Greška: Nije vam dozvoljeno da pozivate nekoga u ovu sobu.',
+ errorUninviteNotAllowed: 'Greška: Nije vam dozvoljeno da nekoga opozovete iz ove sobe.',
+ errorNoOpenQuery: 'Greška: Privatna soba nije otvorena.',
+ errorKickNotAllowed: 'Greška: Nije vam dozvoljeno da izbacite %s.',
+ errorCommandNotAllowed: 'Greška: Komanda nije dozvoljena: %s',
+ errorUnknownCommand: 'Greška: Nepoznata komanda: %s',
+ errorMaxMessageRate: 'Error: You exceeded the maximum number of messages per minute.',
+ errorConnectionTimeout: 'Greška: Vreme konekcije je isteklo. Molimo vas pokušajte ponovo.',
+ errorConnectionStatus: 'Greška: Status konekcije: %s',
+ errorSoundIO: 'Error: Failed to load sound file (Flash IO Error).',
+ errorSocketIO: 'Error: Connection to socket server failed (Flash IO Error).',
+ errorSocketSecurity: 'Error: Connection to socket server failed (Flash Security Error).',
+ errorDOMSyntax: 'Error: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/sv.js b/library/ajaxchat/chat/js/lang/sv.js
new file mode 100644
index 000000000..6c8ded6cc
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/sv.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Eric [June 7,2008]
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s loggade in på Chatten.',
+ logout: '%s loggade ut från Chatten.',
+ logoutTimeout: '%s loggades ut (Timeout).',
+ logoutIP: '%s loggades ut (Felaktig IPadress).',
+ logoutKicked: '%s har loggats ut (Utsparkad).',
+ channelEnter: '%s ansluter till kanalen.',
+ channelLeave: '%s lämnade kanalen.',
+ privmsg: '(Viskning)',
+ privmsgto: '(Viskar till %s)',
+ invite: '%s bjuder in dig att ansluta till %s.',
+ inviteto: 'Din inbjudan till %s att ansluta till kanalen %s har skickats.',
+ uninvite: '%s upphävde inbjudan till dig från kanalen %s.',
+ uninviteto: 'Din uphävning av inbjudan till %s för kanalen %s har skickats.',
+ queryOpen: 'Privat kanal öppnad för %s.',
+ queryClose: 'Privat kanal för %s är stängd.',
+ ignoreAdded: '%s blev inlagd i ignoreringslistan.',
+ ignoreRemoved: 'Ta bort %s från ignoreringslistan.',
+ ignoreList: 'Ignorerade användare:',
+ ignoreListEmpty: 'Inga ignorerade Användare.',
+ who: 'Användare OnLine:',
+ whoChannel: 'Användare OnLine i kanalen %s:',
+ whoEmpty: 'Inga användare OnLine i kanalen.',
+ list: 'Tillgängliga kanaler:',
+ bans: 'Bannade Användare:',
+ bansEmpty: 'Inga bannade Användare.',
+ unban: 'Banningen av %s är upphävd.',
+ whois: '%s - IPadress:',
+ whereis: '%s är i kanalen %s.',
+ roll: '%s rullar %s och får %s.',
+ nick: '%s har bytt namn till %s.',
+ toggleUserMenu: 'Skifta användarmeny för %s',
+ userMenuLogout: 'Logga Ut',
+ userMenuWho: 'Lista användare OnLine',
+ userMenuList: 'Lista tillgängliga kanaler',
+ userMenuAction: 'Beskriv händelse',
+ userMenuRoll: 'Rulla tärningar',
+ userMenuNick: 'Ändra användarnamn',
+ userMenuEnterPrivateRoom: 'Gå in i privat rum',
+ userMenuSendPrivateMessage: 'Skicka privat meddelande',
+ userMenuDescribe: 'Skicka privat händelse',
+ userMenuOpenPrivateChannel: 'Öppna privat kanal',
+ userMenuClosePrivateChannel: 'Stäng privat kanal',
+ userMenuInvite: 'Bjud in',
+ userMenuUninvite: 'Upphäv inbjudan',
+ userMenuIgnore: 'Ignorera/Acceptera',
+ userMenuIgnoreList: 'Lista ignorerade användare',
+ userMenuWhereis: 'Visa kanal',
+ userMenuKick: 'Sparka ut/Banna',
+ userMenuBans: 'Lista bannade användare',
+ userMenuWhois: 'Visa IP',
+ unbanUser: 'Upphäv banningen av %s',
+ joinChannel: 'Anslut till kanalen %s',
+ cite: '%s sa:',
+ urlDialog: 'Skriv in adressen (URL) till websidan:',
+ deleteMessage: 'Radera detta meddelande',
+ deleteMessageConfirm: 'Vill du radera det valda meddelandet?',
+ errorCookiesRequired: 'Cookies[kakor] krävs för denna Chat.',
+ errorUserNameNotFound: 'Error: Användaren %s hittades inte.',
+ errorMissingText: 'Error: Meddelandetext saknas.',
+ errorMissingUserName: 'Error: Användarnamn saknas.',
+ errorInvalidUserName: 'Error: Ogiltigt användarnamn.',
+ errorUserNameInUse: 'Error: Användarnamnet används redan.',
+ errorMissingChannelName: 'Error: Kanalnamn saknas.',
+ errorInvalidChannelName: 'Error: Felaktigt kanalnamn: %s',
+ errorPrivateMessageNotAllowed: 'Error: Privata meddelanden är inte tillåtna.',
+ errorInviteNotAllowed: 'Error: Du saknar rättighet att bjuda in någon till denna kanalen.',
+ errorUninviteNotAllowed: 'Error: Du saknar rättighet att upphäva en inbjudan till någon i denna kanalen.',
+ errorNoOpenQuery: 'Error: Ingen privat kanal öppen.',
+ errorKickNotAllowed: 'Error: Du saknar rättighet att sparka %s.',
+ errorCommandNotAllowed: 'Error: Otillåtet kommando: %s',
+ errorUnknownCommand: 'Error: Okänt kommando: %s',
+ errorMaxMessageRate: 'Error: Du överskred det maxiamala antalet meddelanden per minut.',
+ errorConnectionTimeout: 'Error: Anslutningen fick "timeout". Var vänlig och prova igen.',
+ errorConnectionStatus: 'Error: Anslutningens status: %s',
+ errorSoundIO: 'Error: Misslyckades att ladda ljudfil (Flash IO Error).',
+ errorSocketIO: 'Error: Anslutningen till "socket server" misslyckades (Flash IO Error).',
+ errorSocketSecurity: 'Error: Anslutningen till "socket server" misslyckades (Flash Security Error).',
+ errorDOMSyntax: 'Error: Ogiltig DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/th.js b/library/ajaxchat/chat/js/lang/th.js
new file mode 100644
index 000000000..35c60a51b
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/th.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ * @Translate by Charge01 @ http://www.thaira2lovers.co.cc
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s เข้าสู่ห้องแชท',
+ logout: '%s ออกจากห้องแชท',
+ logoutTimeout: '%s ออกจากห้องแชทแล้ว (Timeout).',
+ logoutIP: '%s ออกจากระบบแล้ว (IP address ไม่ถูกต้อง).',
+ logoutKicked: '%s ออกจากระบบแล้ว (ถูกไล่).',
+ channelEnter: '%s เข้าห้องมา',
+ channelLeave: '%s ออกห้องไป',
+ privmsg: '(กระซิบ)',
+ privmsgto: '(กระซิบไป %s)',
+ invite: '%s เชิญให้ %s เข้าร่วม',
+ inviteto: 'การเชิญ %s เพื่อเข้าสู่ห้อง %s ถูกส่งแล้ว',
+ uninvite: '%s ถอนคำเชิญออกจากห้อง %s.',
+ uninviteto: 'การเชิญ %s สำหรับห้อง %s ถูกส่งแล้ว',
+ queryOpen: 'ห้องส่วนตัวถูกเปิดที่ %s',
+ queryClose: 'ห้องส่วนตัว %s ถูกปิด',
+ ignoreAdded: 'เพิ่ม %s สู่รายการไม่สนใจ',
+ ignoreRemoved: 'ลบ %s ออกจากรายการไม่สนใจ',
+ ignoreList: 'ผู้ใช้ที่ถูกไม่สนใจ:',
+ ignoreListEmpty: 'ไม่มีผู้ใช้ที่ไม่สนใจ',
+ who: 'ผู้ใช้ออนไลนอยู่:',
+ whoChannel: 'ผู้ใช้ออนไลน์ในห้อง %s:',
+ whoEmpty: 'ไม่มีผู้ใช้ออนไลน์อยู่ในห้อง',
+ list: 'ห้องแชทที่มีอยู่:',
+ bans: 'ผู้ใช้ถูกแบน:',
+ bansEmpty: 'ไม่มีผู้ใช้ที่ถูกแบน',
+ unban: 'การแบนของ %s ถูกยกเลิก',
+ whois: 'ผู้ใช้ %s - IP address:',
+ whereis: 'ผู้ใช้ %s อยู่ในห้อง %s.',
+ roll: '%s rolls %s and gets %s.',
+ nick: '%s ตอนนี้เปลี่ยนชื่อเป็น %s.',
+ toggleUserMenu: 'เปิดเมนูสำหรับ %s',
+ userMenuLogout: 'ออกจากระบบ',
+ userMenuWho: 'รายชื่อผู้ใช้',
+ userMenuList: 'รายชื่อห้องที่ปรากฎ',
+ userMenuAction: 'บอกกล่าวการกระทำ',
+ userMenuRoll: 'ทอยลูกเต๋า',
+ userMenuNick: 'เปลี่ยนชื่อ',
+ userMenuEnterPrivateRoom: 'เข้้าห้องส่วนตัว',
+ userMenuSendPrivateMessage: 'ส่งข้อความส่วนตัว',
+ userMenuDescribe: 'ส่งการกระทำส่วนตัว',
+ userMenuOpenPrivateChannel: 'เปิดห้องแชทส่วนตัว',
+ userMenuClosePrivateChannel: 'ปิดห้องแชทส่วนตัว',
+ userMenuInvite: 'เชิญ',
+ userMenuUninvite: 'ถอนคำเชิญ',
+ userMenuIgnore: 'ไม่สนใจ/ยอมรับ',
+ userMenuIgnoreList: 'รายชื่อผู้ใช้ที่ไม่สนใจ',
+ userMenuWhereis: 'แสดงห้องแชท',
+ userMenuKick: 'ไล่/แบน',
+ userMenuBans: 'รายชื่อที่ถูกแบน',
+ userMenuWhois: 'แสดง IP',
+ unbanUser: 'ปลดการแบนของผู้ใช้ %s',
+ joinChannel: 'ร่วมห้อง %s',
+ cite: '%s พูด:',
+ urlDialog: 'กรุณาใส่ที่อยู่เว็บ (URL):',
+ deleteMessage: 'ลบข้อความแชทนี้',
+ deleteMessageConfirm: 'แน่ใจว่าจะลบข้อความที่เลือกนี้?',
+ errorCookiesRequired: 'ห้องแชทนี้ต้องการใช้งานคุกกี้',
+ errorUserNameNotFound: 'Error: ไม่พบผู้ใช้ %s',
+ errorMissingText: 'Error: ข้อความหายไป',
+ errorMissingUserName: 'Error: ผู้ใช้หายไป',
+ errorInvalidUserName: 'Error: ผู้ใช้ไม่ถูกต้อง',
+ errorUserNameInUse: 'Error: ผู้ใช้นี้ถูกใช้งานอยู่',
+ errorMissingChannelName: 'Error: ชื่อห้องแชทหายไป',
+ errorInvalidChannelName: 'Error: ชื่อห้องแชทไม่ถูกต้อง: %s',
+ errorPrivateMessageNotAllowed: 'Error: ไม่อนุญาตข้อความส่วนตัว',
+ errorInviteNotAllowed: 'Error: ไม่อนุญาตให้คุณเชิญใครในห้องนี้',
+ errorUninviteNotAllowed: 'Error: ไม่อนุญาตให้คุณถอดการเชิญในห้องนี้',
+ errorNoOpenQuery: 'Error: ไม่เปิดห้องส่วนตัว',
+ errorKickNotAllowed: 'Error: ไม่อนุญาตให้คุณไล่ %s.',
+ errorCommandNotAllowed: 'Error: ไม่อนุญาตคำสั่ง : %s',
+ errorUnknownCommand: 'Error: คำสั่งอะไรเนีย: %s',
+ errorMaxMessageRate: 'Error: ส่งข้อความเกินกำหนดใน 1 นาที',
+ errorConnectionTimeout: 'Error: การเชื่อมต่อหมดเวลา กรุณาลองอีกครั้ง',
+ errorConnectionStatus: 'Error: สถานะการเชื่อมต่อ: %s',
+ errorSoundIO: 'Error: โหลดไฟล์เสียงผิดพลาด (อาจเกิดจาก Flash IO Error, โปรแกรมช่วยดาวน์โหลด).',
+ errorSocketIO: 'Error: การเชื่อมต่อถึง socket เซิร์ฟเวอร์ผิดพลาด (อาจเกิดจาก Flash IO Error).',
+ errorSocketSecurity: 'Error: การเชื่อมต่อถึง socket เซิร์ฟเวอร์ผิดพลาด (Flash Security Error).',
+ errorDOMSyntax: 'Error: DOM Syntax ไม่ถูกต้อง (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/tr.js b/library/ajaxchat/chat/js/lang/tr.js
new file mode 100644
index 000000000..63d9b5aee
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/tr.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Cydonian
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s sohbet odasına girdi.',
+ logout: '%s sohbet odasından çıktı.',
+ logoutTimeout: '%s sohbetten çıkarıldı (Bağlantı Gecikmesi).',
+ logoutIP: '%s sohbetten çıkarıldı (Geçersiz IP adresi).',
+ logoutKicked: '%s sohbetten çıkarıldı (Atıldı).',
+ channelEnter: '%s kanala girdi.',
+ channelLeave: '%s kanaldan çıktı.',
+ privmsg: '(fısıldıyor)',
+ privmsgto: '(%s size fısıldıyor)',
+ invite: '%s sizi %s odasına davet ediyor.',
+ inviteto: '%s kanalı için davetiniz %s e gönderildi.',
+ uninvite: '%s sizi %s kanalından çıkmaya çağırıyor.',
+ uninviteto: '%s kanalından çıkma davetiniz %s e gönderildi',
+ queryOpen: '%s e özel kanal açıldı.',
+ queryClose: '%s e özel kanal kapatıldı.',
+ ignoreAdded: '%s blok listesine eklendi.',
+ ignoreRemoved: '%s blok listesinden çıkarıldı.',
+ ignoreList: 'Blok edilen üyeler:',
+ ignoreListEmpty: 'Blok Listesi boş.',
+ who: 'Çevrimiçi üyeler:',
+ whoChannel: '%s kanalındaki çevrimiçi üyeler:',
+ whoEmpty: 'Kanalda çevrimiçi üye yoktur.',
+ list: 'Açık Odalar:',
+ bans: 'Yasaklanan Üyeler:',
+ bansEmpty: 'Yasaklı Listesi boş.',
+ unban: '%s adlı üyenin yasağı kaldırıldı.',
+ whois: 'Üye %s - IP adresi:',
+ whereis: '%s adlı üye %s kanalında.',
+ roll: '%s sallar %s ve alır %s.',
+ nick: '%s rumuzunu %s yaptı.',
+ toggleUserMenu: 'Toggle user menu for %s',
+ userMenuLogout: 'Çıkış',
+ userMenuWho: 'Çevrimiçi üyeleri göster',
+ userMenuList: 'Uygun odaları göster',
+ userMenuAction: 'Aksiyon:',
+ userMenuRoll: 'Zarları at',
+ userMenuNick: 'Rumuz değiştir',
+ userMenuEnterPrivateRoom: 'Özel odaya gir',
+ userMenuSendPrivateMessage: 'Özel mesaj gönder',
+ userMenuDescribe: 'Özel aksiyon gönder',
+ userMenuOpenPrivateChannel: 'Özel kanal aç',
+ userMenuClosePrivateChannel: 'Özel kanalı kapat',
+ userMenuInvite: 'Davet et',
+ userMenuUninvite: 'Davet etme',
+ userMenuIgnore: 'İptal/Kabul',
+ userMenuIgnoreList: 'Bloklanmış üyeleri göster',
+ userMenuWhereis: 'Kanalı göster',
+ userMenuKick: 'At/Yasakla',
+ userMenuBans: 'Yasaklanmış üyeleri göster',
+ userMenuWhois: 'IP göster',
+ unbanUser: 'Üye %s nin yasağını kaldır',
+ joinChannel: '%s kanalına Gir',
+ cite: '%s :',
+ urlDialog: 'Web sayfasının adresini (URL) giriniz:',
+ deleteMessage: 'Bu mesajı sil',
+ deleteMessageConfirm: 'İşaretli mesajı gerçekten silmek istiyor musunuz?',
+ errorCookiesRequired: 'Bu sohbet için Cookies açık olmalıdır.',
+ errorUserNameNotFound: 'Hata: %s adlı üye bulunamadı.',
+ errorMissingText: 'Hata: Mesaj yazısı yok.',
+ errorMissingUserName: 'Hata: Üye adı yok.',
+ errorInvalidUserName: 'Hata: Geçersiz üye adı.',
+ errorUserNameInUse: 'Hata: Üye adı kullanımda.',
+ errorMissingChannelName: 'Hata: Kanal adı yok.',
+ errorInvalidChannelName: 'Hata: Geçersiz kanal adı: %s',
+ errorPrivateMessageNotAllowed: 'Hata: Özel mesajlara izin verilmiyor.',
+ errorInviteNotAllowed: 'Hata: Başka bir üyeyi bu kanala davet etme izniniz yok.',
+ errorUninviteNotAllowed: 'Hata: Başka bir üyeyi bu kanaldan dışarı davete izniniz yok.',
+ errorNoOpenQuery: 'Hata: Açık özel kanal yok.',
+ errorKickNotAllowed: 'Hata: %s adlı üyeyi atma yetkiniz yok.',
+ errorCommandNotAllowed: 'Hata: Bu komuta izin yok: %s',
+ errorUnknownCommand: 'Hata: Bilinmeyen komut: %s',
+ errorMaxMessageRate: 'Hata: Bir dakika içinde atılabilecek maksimum mesaj sayısına ulaştınız.',
+ errorConnectionTimeout: 'Hata: Bağlantı süresi aşımı. Lütfen tekrar deneyin.',
+ errorConnectionStatus: 'Hata: Bağlantı durumu: %s',
+ errorSoundIO: 'Hata: Ses dosyası yüklenemedi (Flash IO Hatası).',
+ errorSocketIO: 'Hata: Socket server bağlantısı yapılamadı (Flash IO Hatası).',
+ errorSocketSecurity: 'Hata: Socket server bağlantısı yapılamadı(Flash Güvenlik Hatası).',
+ errorDOMSyntax: 'Hata: Geçersiz DOM Sözdizimi (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/uk.js b/library/ajaxchat/chat/js/lang/uk.js
new file mode 100644
index 000000000..42f61804e
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/uk.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Yuriy Smetana (yura@stryi.com.ua, http://joomla.org.ua)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s заходить до Чату.',
+ logout: '%s виходить з Чату.',
+ logoutTimeout: '%s залишає чат (був неактивний).',
+ logoutIP: '%s залишає чат (неправильна IP адреса).',
+ logoutKicked: '%s залишає чат (примусово).',
+ channelEnter: '%s заходить до кімнати.',
+ channelLeave: '%s залишає кімнату.',
+ privmsg: '(пошепки)',
+ privmsgto: '(пошепки до %s)',
+ invite: '%s запрошує відвідати кімнату %s.',
+ inviteto: 'Запрошення до %s відвідати кімнату %s надіслано.',
+ uninvite: '%s відмовив в запрошенні до кімнати %s.',
+ uninviteto: 'Відміну запрошення %s до кімнати %s було надіслано.',
+ queryOpen: 'Створено приватну кімнату з %s.',
+ queryClose: 'Приватну кімнату з %s зачинено.',
+ ignoreAdded: '%s додано до переліку ігнорованих осіб.',
+ ignoreRemoved: '%s вилучено з переліку ігнорованих осіб.',
+ ignoreList: 'Ігроновані особи:',
+ ignoreListEmpty: 'Ігнорованих осіб немає.',
+ who: 'Зараз в Чаті:',
+ whoChannel: 'Зараз в кімнаті %s такі користувачі:',
+ whoEmpty: 'Ця кімната порожня.',
+ list: 'Інші кімнати:',
+ bans: 'Заблоковані користувачі:',
+ bansEmpty: 'Немає заблокованих користувачів.',
+ unban: 'Блокування користувача %s відмінено.',
+ whois: 'Користувач %s - IP адреса:',
+ whereis: 'Користувач %s в кімнаті %s.',
+ roll: 'Користувачем %s кинуто %s, випало %s.',
+ nick: 'Користувач %s відтепер буде називатись %s.',
+ toggleUserMenu: 'Меню користувача %s',
+ userMenuLogout: 'Вийти',
+ userMenuWho: 'Показати присутніх',
+ userMenuList: 'Показати кімнати',
+ userMenuAction: 'Описати чим зараз займаєтесь',
+ userMenuRoll: 'Кинути кості',
+ userMenuNick: 'Змінити собі ім\'я',
+ userMenuEnterPrivateRoom: 'Увійти до приватної кімнати',
+ userMenuSendPrivateMessage: 'Надіслати особисте повідомлення',
+ userMenuDescribe: 'Описати чим займаєтесь (приватно)',
+ userMenuOpenPrivateChannel: 'Створити приватну кімнату',
+ userMenuClosePrivateChannel: 'Закрити приватну кімнату',
+ userMenuInvite: 'Запросити',
+ userMenuUninvite: 'Відмовити',
+ userMenuIgnore: 'Ігнорувати/Приймати',
+ userMenuIgnoreList: 'Перелік ігнорованих',
+ userMenuWhereis: 'Показати кімнати',
+ userMenuKick: 'Викинути/Заблокувати',
+ userMenuBans: 'Перелік заблокованих користувачів',
+ userMenuWhois: 'Показати IP',
+ unbanUser: 'Відмінити блокування користувача %s',
+ joinChannel: 'Зайти в кімнату %s',
+ cite: '%s пише:',
+ urlDialog: 'Будь-ласка, введіть адресу веб-сторінки:',
+ deleteMessage: 'Видалити це повідомлення',
+ deleteMessageConfirm: 'Справді видалити це повідомлення?',
+ errorCookiesRequired: 'Для Чату необхідно дозволити Cookies.',
+ errorUserNameNotFound: 'Помилка: користувач %s не існує.',
+ errorMissingText: 'Помилка: повідомлення відсутнє.',
+ errorMissingUserName: 'Помилка: відсутнє ім\'я користувача.',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: 'Помилка: відсутня назва кімнати.',
+ errorInvalidChannelName: 'Помилка: хибна назва кімнати: %s',
+ errorPrivateMessageNotAllowed: 'Помилка: приватні повідомлення заборонені.',
+ errorInviteNotAllowed: 'Помилка: Вам заборонено запрошувати до цієї кімнати.',
+ errorUninviteNotAllowed: 'Помилка: Вам заборонено відмовляти в запрошенні до цієї кімнати.',
+ errorNoOpenQuery: 'Помилка: не існує приватних кімнат.',
+ errorKickNotAllowed: 'Помилка: Вам недозволено викидати користувачів %s.',
+ errorCommandNotAllowed: 'Помилка: недозволена команда: %s',
+ errorUnknownCommand: 'Помилка: хибна команда: %s',
+ errorMaxMessageRate: 'Помилка: Ви досягли максимальної кількості повідомлень за хвилину.',
+ errorConnectionTimeout: 'Помилка: час очікування минув. Будь-ласка, спробуйте знову.',
+ errorConnectionStatus: 'Помилка: стан з\'єднання: %s',
+ errorSoundIO: 'Помилка: Неможливо відкрити звуковий файл (Flash IO Error).',
+ errorSocketIO: 'Помилка: З\'єднання з сервером невдалося (Flash IO Error).',
+ errorSocketSecurity: 'Помилка: З\'єднання з сервером невдалося (Flash Security Error).',
+ errorDOMSyntax: 'Помилка: Invalid DOM Syntax (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/zh-tw.js b/library/ajaxchat/chat/js/lang/zh-tw.js
new file mode 100644
index 000000000..c6b971953
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/zh-tw.js
@@ -0,0 +1,91 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s已登入',
+ logout: '%s已登出',
+ logoutTimeout: '%s已登出(連線逾時)',
+ logoutIP: '%s已登出(無效的IP address)',
+ logoutKicked: '%s已登出(被踢掉了)',
+ channelEnter: '%s已進入',
+ channelLeave: '%s已離開',
+ privmsg: '(悄悄話)',
+ privmsgto: '(給 %s 的悄悄話)',
+ invite: '%s 邀請您進入 %s .',
+ inviteto: '請 %s 進入 %s 的邀請函已發送',
+ uninvite: '%s 於 %s 收回了邀請函',
+ uninviteto: '請 %s 進入 %s 的邀請函已收回',
+ queryOpen: '允許 %s 進入私人房',
+ queryClose: '已不允許 %s 進入私人房',
+ ignoreAdded: '增加 %s 至忽略清單',
+ ignoreRemoved: '移除 %s 自忽略清單',
+ ignoreList: '已忽略來自以下人士的訊息:',
+ ignoreListEmpty: '忽略清單是空的。',
+ who: '已上線會員:',
+ whoChannel: '在 %s 的已上線會員:',
+ whoEmpty: '沒有人在那裡。',
+ list: '可進入的房間:',
+ bans: '被禁止使用的人:',
+ bansEmpty: '沒有被禁止使用的人。',
+ unban: '開放之前被禁的使用者 %s :',
+ whois: '使用者 %s - IP address:',
+ whereis: '使用者 %s 正在 %s 。',
+ roll: '%s 擲了 %s 得到了 %s 。',
+ nick: '%s 現在暱稱改為 %s',
+ toggleUserMenu: '開啟為 %s 特製的功能表',
+ userMenuLogout: '登出',
+ userMenuWho: '顯示已上線會員',
+ userMenuList: '顯示可進入的房間',
+ userMenuAction: '描述動作',
+ userMenuRoll: '擲骰子',
+ userMenuNick: '換暱稱',
+ userMenuEnterPrivateRoom: '進入私人房',
+ userMenuSendPrivateMessage: '傳送悄悄話',
+ userMenuDescribe: '傳送私人動作',
+ userMenuOpenPrivateChannel: '允許進入私人房',
+ userMenuClosePrivateChannel: '不允許進入私人房',
+ userMenuInvite: '邀請某人(進入自己的私人房)',
+ userMenuUninvite: '收回邀請',
+ userMenuIgnore: '忽略/接受某人的訊息',
+ userMenuIgnoreList: '顯示忽略清單',
+ userMenuWhereis: '顯示所在地',
+ userMenuKick: '踢掉/禁人',
+ userMenuBans: '顯示被禁的使用者',
+ userMenuWhois: '顯示 IP',
+ unbanUser: '開放之前被禁的使用者 %s ',
+ joinChannel: '進入 %s',
+ cite: '%s 說:',
+ urlDialog: '請輸入網址(URL):',
+ deleteMessage: '刪除這條訊息',
+ deleteMessageConfirm: '真的要刪除這條訊息嗎?',
+ errorCookiesRequired: '請打開Cookies!',
+ errorUserNameNotFound: '錯誤:沒有使用者 %s ……',
+ errorMissingText: '錯誤:未輸入訊息……',
+ errorMissingUserName: '錯誤:未輸入使用者帳號……',
+ errorInvalidUserName: '錯誤:帳號錯誤……',
+ errorUserNameInUse: '錯誤:帳號使用中……',
+ errorMissingChannelName: '錯誤:不存在的房間……',
+ errorInvalidChannelName: '錯誤:不存在的房間: %s ……',
+ errorPrivateMessageNotAllowed: '錯誤:不允許使用悄悄話功能……',
+ errorInviteNotAllowed: '錯誤:不允許邀請別人來這裡……',
+ errorUninviteNotAllowed: '錯誤:不允許收回邀請……',
+ errorNoOpenQuery: '錯誤:沒有私人房是開放的……',
+ errorKickNotAllowed: '錯誤:你不能把 %s 踢掉!',
+ errorCommandNotAllowed: '錯誤:不允許使用的指令: %s ……',
+ errorUnknownCommand: '錯誤:無法辨識的命令: %s ……',
+ errorMaxMessageRate: '錯誤:已達到一分鐘所能發送的最大訊息數量……',
+ errorConnectionTimeout: '錯誤:連線逾時,請再連一次……',
+ errorConnectionStatus: '錯誤:連線狀態: %s ',
+ errorSoundIO: '錯誤:無法讀取音效檔 (Flash IO Error).',
+ errorSocketIO: '錯誤:無法連線到伺服器的socket (Flash IO Error).',
+ errorSocketSecurity: '錯誤:無法連線到伺服器的socket (Flash Security Error).',
+ errorDOMSyntax: '錯誤:無效的 DOM 語法 (DOM ID: %s).'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/lang/zh.js b/library/ajaxchat/chat/js/lang/zh.js
new file mode 100644
index 000000000..ba41fad7f
--- /dev/null
+++ b/library/ajaxchat/chat/js/lang/zh.js
@@ -0,0 +1,92 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author mikespook
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat language Object:
+var ajaxChatLang = {
+
+ login: '%s 进入聊天室。',
+ logout: '%s 退出聊天室。',
+ logoutTimeout: '%s 因超时,退出聊天室。',
+ logoutIP: '%s 因不合法的 IP 地址退出。',
+ logoutKicked: '%s 被踢出聊天室。',
+ channelEnter: '%s 进入频道。',
+ channelLeave: '%s 退出频道。',
+ privmsg: '(悄悄话)',
+ privmsgto: '(对 %s 说悄悄话)',
+ invite: '%s 邀请你加入 %s。',
+ inviteto: '对 %s 在频道 %s 的邀请已经发送。',
+ uninvite: '%s 撤销了你在频道 %s 的邀请。',
+ uninviteto: '对 %s 在频道 %s 的撤销邀请已经发送。',
+ queryOpen: '私人频道对 %s 打开。',
+ queryClose: '私人频道对 %s 关闭。',
+ ignoreAdded: '将 %s 加入忽略列表。',
+ ignoreRemoved: '从忽略列表中移除 %s。',
+ ignoreList: '已忽略用户:',
+ ignoreListEmpty: '已列出未忽略用户。',
+ who: '在线用户:',
+ whoChannel: '频道 %s 的在线用户:',
+ whoEmpty: '指定频道中没有在线用户。',
+ list: '可用频道:',
+ bans: '已禁言用户:',
+ bansEmpty: '已列出未禁言用户。',
+ unban: '用户 %s 的禁言已取消。',
+ whois: '用户 %s - IP 地址:',
+ whereis: '用户 %s 进入频道 %s.',
+ roll: '%s 摇出了 %s 并且得到了 %s。',
+ nick: '%s 改名为 %s。',
+ toggleUserMenu: '切换用户 %s 的菜单',
+ userMenuLogout: '退出',
+ userMenuWho: '列出在线用户',
+ userMenuList: '列出可用的频道',
+ userMenuAction: '动作描述',
+ userMenuRoll: '摇骰子',
+ userMenuNick: '修改用户名',
+ userMenuEnterPrivateRoom: '进入私人房间',
+ userMenuSendPrivateMessage: '发送私人消息',
+ userMenuDescribe: '发送私人动作',
+ userMenuOpenPrivateChannel: '打开私人频道',
+ userMenuClosePrivateChannel: '关闭私人频道',
+ userMenuInvite: '邀请',
+ userMenuUninvite: '撤销邀请',
+ userMenuIgnore: '忽略/接收',
+ userMenuIgnoreList: '列出忽略的用户',
+ userMenuWhereis: '显示频道',
+ userMenuKick: '踢/禁',
+ userMenuBans: '列出禁言的用户',
+ userMenuWhois: '显示 IP',
+ unbanUser: '撤销用户 %s 禁言',
+ joinChannel: '加入频道 %s',
+ cite: '%s 说:',
+ urlDialog: '请输入网页地址(URL):',
+ deleteMessage: '删除聊天记录',
+ deleteMessageConfirm: '要删除已经发出的聊天记录吗?',
+ errorCookiesRequired: '聊天室需要开启 Cookie 功能。',
+ errorUserNameNotFound: '错误:未找到用户 %s。',
+ errorMissingText: '错误:缺少消息内容。',
+ errorMissingUserName: '错误:缺少用户名。',
+ errorInvalidUserName: 'Error: Invalid username.',
+ errorUserNameInUse: 'Error: Username already in use.',
+ errorMissingChannelName: '错误:缺少频道名。',
+ errorInvalidChannelName: '错误:错误的频道名:%s',
+ errorPrivateMessageNotAllowed: '错误:不允许发送私人消息。',
+ errorInviteNotAllowed: '错误:你在这个频道没有权限邀请他人。',
+ errorUninviteNotAllowed: '错误:你在这个频道没有权限取消邀请。',
+ errorNoOpenQuery: '错误:没有私人频道开放。',
+ errorKickNotAllowed: '错误:没有权限提出 %s。',
+ errorCommandNotAllowed: '错误:不允许的命令:%s',
+ errorUnknownCommand: '错误:未知命令:%s',
+ errorMaxMessageRate: '错误:超出了每分钟最大讯息数。',
+ errorConnectionTimeout: '错误:连接超时,请重试。',
+ errorConnectionStatus: '错误:连接状态:%s',
+ errorSoundIO: '错误:加载声音文件失败(Flash IO 错误)。',
+ errorSocketIO: '错误:连接 Socket 服务器失败(Flash IO 错误)。',
+ errorSocketSecurity: '错误:连接 Socket 服务器失败(Flash 安全错误)。',
+ errorDOMSyntax: '错误:错误的 DOM 语法(DOM ID:%s)。'
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/logs.js b/library/ajaxchat/chat/js/logs.js
new file mode 100644
index 000000000..9ec694cee
--- /dev/null
+++ b/library/ajaxchat/chat/js/logs.js
@@ -0,0 +1,128 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Overrides client-side functionality for the logs view:
+
+ ajaxChat.logsMonitorMode = null;
+ ajaxChat.logsLastID = null;
+ ajaxChat.logsCommand = null;
+
+ ajaxChat.startChatUpdate = function() {
+ var infos = 'userID,userName,userRole';
+ if(this.socketServerEnabled) {
+ infos += ',socketRegistrationID';
+ }
+ this.updateChat('&getInfos=' + this.encodeText(infos));
+ }
+
+ ajaxChat.updateChat = function(paramString) {
+ // Only update if we have parameters, are in monitor mode or the lastID has changed since the last update:
+ if(paramString || this.logsMonitorMode || !this.logsLastID || this.lastID != this.logsLastID) {
+ // Update the logsLastID for the lastID check:
+ this.logsLastID = this.lastID;
+
+ var requestUrl = this.ajaxURL
+ + '&lastID='
+ + this.lastID;
+ if(paramString) {
+ requestUrl += paramString;
+ }
+ requestUrl += '&' + this.getLogsCommand();
+ this.makeRequest(requestUrl,'GET',null);
+ } else {
+ this.logsLastID = null;
+ }
+ }
+
+ ajaxChat.sendMessage = function() {
+ this.getLogs();
+ }
+
+ ajaxChat.getLogs = function() {
+ clearTimeout(this.timer);
+ this.clearChatList();
+ this.lastID = 0;
+ this.logsCommand = null;
+ this.makeRequest(this.ajaxURL,'POST',this.getLogsCommand());
+ }
+
+ ajaxChat.getLogsCommand = function() {
+ if(!this.logsCommand) {
+ if(!this.dom['inputField'].value &&
+ parseInt(this.dom['yearSelection'].value) <= 0 &&
+ parseInt(this.dom['hourSelection'].value) <= 0) {
+ this.logsMonitorMode = true;
+ } else {
+ this.logsMonitorMode = false;
+ }
+ this.logsCommand = 'command=getLogs'
+ + '&channelID=' + this.dom['channelSelection'].value
+ + '&year=' + this.dom['yearSelection'].value
+ + '&month=' + this.dom['monthSelection'].value
+ + '&day=' + this.dom['daySelection'].value
+ + '&hour=' + this.dom['hourSelection'].value
+ + '&search=' + this.encodeText(this.dom['inputField'].value);
+ }
+ return this.logsCommand;
+ }
+
+ ajaxChat.onNewMessage = function(dateObject, userID, userName, userRoleClass, messageID, messageText, channelID, ip) {
+ if(messageText.indexOf('/delete') == 0) {
+ return false;
+ }
+ if(this.logsMonitorMode) {
+ this.blinkOnNewMessage(dateObject, userID, userName, userRoleClass, messageID, messageText, channelID, ip);
+ this.playSoundOnNewMessage(
+ dateObject, userID, userName, userRoleClass, messageID, messageText, channelID, ip
+ );
+ }
+ return true;
+ }
+
+ ajaxChat.logout = function() {
+ clearTimeout(this.timer);
+ this.makeRequest(this.ajaxURL,'POST','logout=true');
+ }
+
+ ajaxChat.switchLanguage = function(langCode) {
+ window.location.search = '?view=logs&lang='+langCode;
+ }
+
+ ajaxChat.setChatUpdateTimer = function() {
+ clearTimeout(this.timer);
+ var timeout;
+ if(this.socketIsConnected && this.logsLastID && this.lastID == this.logsLastID) {
+ timeout = this.socketTimerRate;
+ } else {
+ timeout = this.timerRate;
+ if(this.socketServerEnabled && !this.socketReconnectTimer) {
+ // If the socket connection fails try to reconnect once in a minute:
+ this.socketReconnectTimer = setTimeout('ajaxChat.socketConnect();', 60000);
+ }
+ }
+ this.timer = setTimeout('ajaxChat.updateChat(null);', timeout);
+ }
+
+ ajaxChat.socketUpdate = function(data) {
+ if(this.logsMonitorMode) {
+ var xmlDoc = this.loadXML(data);
+ if(xmlDoc) {
+ var selectedChannelID = parseInt(this.dom['channelSelection'].value);
+ var channelID = parseInt(xmlDoc.firstChild.getAttribute('channelID'));
+ if(selectedChannelID == -3 || channelID == selectedChannelID ||
+ selectedChannelID == -2 && channelID >= this.privateMessageDiff ||
+ selectedChannelID == -1
+ && channelID >= this.privateChannelDiff
+ && channelID < this.privateMessageDiff
+ ) {
+ this.handleChatMessages(xmlDoc.getElementsByTagName('message'));
+ }
+ }
+ }
+ }
+ \ No newline at end of file
diff --git a/library/ajaxchat/chat/js/shoutbox.js b/library/ajaxchat/chat/js/shoutbox.js
new file mode 100644
index 000000000..b283277a7
--- /dev/null
+++ b/library/ajaxchat/chat/js/shoutbox.js
@@ -0,0 +1,12 @@
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Overrides functionality for the shoutbox view:
+
+ ajaxChat.handleLogout = function() {
+ }
diff --git a/library/ajaxchat/chat/lib/.htaccess b/library/ajaxchat/chat/lib/.htaccess
new file mode 100644
index 000000000..91e386dc9
--- /dev/null
+++ b/library/ajaxchat/chat/lib/.htaccess
@@ -0,0 +1,4 @@
+AuthType Basic
+AuthName "Forbidden"
+AuthUserFile /dev/null
+require user nobody \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChat.php b/library/ajaxchat/chat/lib/class/AJAXChat.php
new file mode 100644
index 000000000..2cf7aa11f
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChat.php
@@ -0,0 +1,3326 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Ajax Chat backend logic:
+class AJAXChat {
+
+ var $db;
+ var $_config;
+ var $_requestVars;
+ var $_infoMessages;
+ var $_channels;
+ var $_allChannels;
+ var $_view;
+ var $_lang;
+ var $_invitations;
+ var $_customVars;
+ var $_sessionNew;
+ var $_onlineUsersData;
+ var $_bannedUsersData;
+
+ function __construct() {
+ $this->initialize();
+ }
+
+ function initialize() {
+ // Initialize configuration settings:
+ $this->initConfig();
+
+ // Initialize the DataBase connection:
+ $this->initDataBaseConnection();
+
+ // Initialize request variables:
+ $this->initRequestVars();
+
+ // Initialize the chat session:
+ $this->initSession();
+
+ // Handle the browser request and send the response content:
+ $this->handleRequest();
+ }
+
+ function initConfig() {
+ $config = null;
+ if (!include(AJAX_CHAT_PATH.'lib/config.php')) {
+ echo('<strong>Error:</strong> Could not find a config.php file in "'.AJAX_CHAT_PATH.'"lib/". Check to make sure the file exists.');
+ die();
+ }
+ $this->_config = &$config;
+
+ // Initialize custom configuration settings:
+ $this->initCustomConfig();
+ }
+
+ function initRequestVars() {
+ $this->_requestVars = array();
+ $this->_requestVars['ajax'] = isset($_REQUEST['ajax']) ? true : false;
+ $this->_requestVars['userID'] = isset($_REQUEST['userID']) ? (int)$_REQUEST['userID'] : null;
+ $this->_requestVars['userName'] = isset($_REQUEST['userName']) ? $_REQUEST['userName'] : null;
+ $this->_requestVars['channelID'] = isset($_REQUEST['channelID']) ? (int)$_REQUEST['channelID'] : null;
+ $this->_requestVars['channelName'] = isset($_REQUEST['channelName']) ? $_REQUEST['channelName'] : null;
+ $this->_requestVars['text'] = isset($_POST['text']) ? $_POST['text'] : null;
+ $this->_requestVars['lastID'] = isset($_REQUEST['lastID']) ? (int)$_REQUEST['lastID'] : 0;
+ $this->_requestVars['login'] = isset($_REQUEST['login']) ? true : false;
+ $this->_requestVars['logout'] = isset($_REQUEST['logout']) ? true : false;
+ $this->_requestVars['password'] = isset($_REQUEST['password']) ? $_REQUEST['password'] : null;
+ $this->_requestVars['view'] = isset($_REQUEST['view']) ? $_REQUEST['view'] : null;
+ $this->_requestVars['year'] = isset($_REQUEST['year']) ? (int)$_REQUEST['year'] : null;
+ $this->_requestVars['month'] = isset($_REQUEST['month']) ? (int)$_REQUEST['month'] : null;
+ $this->_requestVars['day'] = isset($_REQUEST['day']) ? (int)$_REQUEST['day'] : null;
+ $this->_requestVars['hour'] = isset($_REQUEST['hour']) ? (int)$_REQUEST['hour'] : null;
+ $this->_requestVars['search'] = isset($_REQUEST['search']) ? $_REQUEST['search'] : null;
+ $this->_requestVars['shoutbox'] = isset($_REQUEST['shoutbox']) ? true : false;
+ $this->_requestVars['getInfos'] = isset($_REQUEST['getInfos']) ? $_REQUEST['getInfos'] : null;
+ $this->_requestVars['lang'] = isset($_REQUEST['lang']) ? $_REQUEST['lang'] : null;
+ $this->_requestVars['delete'] = isset($_REQUEST['delete']) ? (int)$_REQUEST['delete'] : null;
+
+ // Initialize custom request variables:
+ $this->initCustomRequestVars();
+
+ // Remove slashes which have been added to user input strings if magic_quotes_gpc is On:
+ if(get_magic_quotes_gpc()) {
+ // It is safe to remove the slashes as we escape user data ourself
+ array_walk(
+ $this->_requestVars,
+ create_function(
+ '&$value, $key',
+ 'if(is_string($value)) $value = stripslashes($value);'
+ )
+ );
+ }
+ }
+
+ function initDataBaseConnection() {
+ // Create a new database object:
+ $this->db = new AJAXChatDataBase(
+ $this->_config['dbConnection']
+ );
+ // Use a new database connection if no existing is given:
+ if(!$this->_config['dbConnection']['link']) {
+ // Connect to the database server:
+ $this->db->connect($this->_config['dbConnection']);
+ if($this->db->error()) {
+ echo $this->db->getError();
+ die();
+ }
+ // Select the database:
+ $this->db->select($this->_config['dbConnection']['name']);
+ if($this->db->error()) {
+ echo $this->db->getError();
+ die();
+ }
+ }
+ // Unset the dbConnection array for safety purposes:
+ unset($this->_config['dbConnection']);
+ }
+
+ function getDataBaseTable($table) {
+ return ($this->db->getName() ? '`'.$this->db->getName().'`.'.$this->getConfig('dbTableNames',$table) : $this->getConfig('dbTableNames',$table));
+ }
+
+ function initSession() {
+ // Start the PHP session (if not already started):
+ $this->startSession();
+
+ if($this->isLoggedIn()) {
+ // Logout if we receive a logout request, the chat has been closed or the userID could not be revalidated:
+ if($this->getRequestVar('logout') || !$this->isChatOpen() || !$this->revalidateUserID()) {
+ $this->logout();
+ return;
+ }
+ // Logout if the Session IP is not the same when logged in and ipCheck is enabled:
+ if($this->getConfig('ipCheck') && ($this->getSessionIP() === null || $this->getSessionIP() != $_SERVER['REMOTE_ADDR'])) {
+ $this->logout('IP');
+ return;
+ }
+ } else if(
+ // Login if auto-login enabled or a login, userName or shoutbox parameter is given:
+ $this->getConfig('forceAutoLogin') ||
+ $this->getRequestVar('login') ||
+ $this->getRequestVar('userName') ||
+ $this->getRequestVar('shoutbox')
+ ) {
+ $this->login();
+ }
+
+ // Initialize the view:
+ $this->initView();
+
+ if($this->getView() == 'chat') {
+ $this->initChatViewSession();
+ } else if($this->getView() == 'logs') {
+ $this->initLogsViewSession();
+ }
+
+ if(!$this->getRequestVar('ajax') && !headers_sent()) {
+ // Set style cookie:
+ $this->setStyle();
+ // Set langCode cookie:
+ $this->setLangCodeCookie();
+ }
+
+ $this->initCustomSession();
+ }
+
+ function initLogsViewSession() {
+ if($this->getConfig('socketServerEnabled')) {
+ if(!$this->getSessionVar('logsViewSocketAuthenticated')) {
+ $this->updateLogsViewSocketAuthentication();
+ $this->setSessionVar('logsViewSocketAuthenticated', true);
+ }
+ }
+ }
+
+ function updateLogsViewSocketAuthentication() {
+ if($this->getUserRole() != AJAX_CHAT_ADMIN) {
+ $channels = array();
+ foreach($this->getChannels() as $channel) {
+ if($this->getConfig('logsUserAccessChannelList') && !in_array($channel, $this->getConfig('logsUserAccessChannelList'))) {
+ continue;
+ }
+ array_push($channels, $channel);
+ }
+ array_push($channels, $this->getPrivateMessageID());
+ array_push($channels, $this->getPrivateChannelID());
+ } else {
+ // The channelID "ALL" authenticates for all channels:
+ $channels = array('ALL');
+ }
+ $this->updateSocketAuthentication(
+ $this->getUserID(),
+ $this->getSocketRegistrationID(),
+ $channels
+ );
+ }
+
+ function initChatViewSession() {
+ // If channel is not null we are logged in to the chat view:
+ if($this->getChannel() !== null) {
+ // Check if the current user has been logged out due to inactivity:
+ if(!$this->isUserOnline()) {
+ $this->logout();
+ return;
+ }
+ if($this->getRequestVar('ajax')) {
+ $this->initChannel();
+ $this->updateOnlineStatus();
+ $this->checkAndRemoveInactive();
+ }
+ } else {
+ if($this->getRequestVar('ajax')) {
+ // Set channel, insert login messages and add to online list on first ajax request in chat view:
+ $this->chatViewLogin();
+ }
+ }
+ }
+
+ function isChatOpen() {
+ if($this->getUserRole() == AJAX_CHAT_ADMIN)
+ return true;
+ if($this->getConfig('chatClosed'))
+ return false;
+ $time = time();
+ if($this->getConfig('timeZoneOffset') !== null) {
+ // Subtract the server timezone offset and add the config timezone offset:
+ $time -= date('Z', $time);
+ $time += $this->getConfig('timeZoneOffset');
+ }
+ // Check the opening hours:
+ if($this->getConfig('openingHour') < $this->getConfig('closingHour'))
+ {
+ if(($this->getConfig('openingHour') > date('G', $time)) || ($this->getConfig('closingHour') <= date('G', $time)))
+ return false;
+ }
+ else
+ {
+ if(($this->getConfig('openingHour') > date('G', $time)) && ($this->getConfig('closingHour') <= date('G', $time)))
+ return false;
+ }
+ // Check the opening weekdays:
+ if(!in_array(date('w', $time), $this->getConfig('openingWeekDays')))
+ return false;
+ return true;
+ }
+
+ function handleRequest() {
+ if($this->getRequestVar('ajax')) {
+ if($this->isLoggedIn()) {
+ // Parse info requests (for current userName, etc.):
+ $this->parseInfoRequests();
+
+ // Parse command requests (e.g. message deletion):
+ $this->parseCommandRequests();
+
+ // Parse message requests:
+ $this->initMessageHandling();
+ }
+ // Send chat messages and online user list in XML format:
+ $this->sendXMLMessages();
+ } else {
+ // Display XHTML content for non-ajax requests:
+ $this->sendXHTMLContent();
+ }
+ }
+
+ function parseCommandRequests() {
+ if($this->getRequestVar('delete') !== null) {
+ $this->deleteMessage($this->getRequestVar('delete'));
+ }
+ }
+
+ function parseInfoRequests() {
+ if($this->getRequestVar('getInfos')) {
+ $infoRequests = explode(',', $this->getRequestVar('getInfos'));
+ foreach($infoRequests as $infoRequest) {
+ $this->parseInfoRequest($infoRequest);
+ }
+ }
+ }
+
+ function parseInfoRequest($infoRequest) {
+ switch($infoRequest) {
+ case 'userID':
+ $this->addInfoMessage($this->getUserID(), 'userID');
+ break;
+ case 'userName':
+ $this->addInfoMessage($this->getUserName(), 'userName');
+ break;
+ case 'userRole':
+ $this->addInfoMessage($this->getUserRole(), 'userRole');
+ break;
+ case 'channelID':
+ $this->addInfoMessage($this->getChannel(), 'channelID');
+ break;
+ case 'channelName':
+ $this->addInfoMessage($this->getChannelName(), 'channelName');
+ break;
+ case 'socketRegistrationID':
+ $this->addInfoMessage($this->getSocketRegistrationID(), 'socketRegistrationID');
+ break;
+ default:
+ $this->parseCustomInfoRequest($infoRequest);
+ }
+ }
+
+ function sendXHTMLContent() {
+ $httpHeader = new AJAXChatHTTPHeader($this->getConfig('contentEncoding'), $this->getConfig('contentType'));
+
+ $template = new AJAXChatTemplate($this, $this->getTemplateFileName(), $httpHeader->getContentType());
+
+ // Send HTTP header:
+ $httpHeader->send();
+
+ // Send parsed template content:
+ echo $template->getParsedContent();
+ }
+
+ function getTemplateFileName() {
+ switch($this->getView()) {
+ case 'chat':
+ return AJAX_CHAT_PATH.'lib/template/loggedIn.html';
+ case 'logs':
+ return AJAX_CHAT_PATH.'lib/template/logs.html';
+ default:
+ return AJAX_CHAT_PATH.'lib/template/loggedOut.html';
+ }
+ }
+
+ function initView() {
+ $this->_view = null;
+ // "chat" is the default view:
+ $view = ($this->getRequestVar('view') === null) ? 'chat' : $this->getRequestVar('view');
+ if($this->hasAccessTo($view)) {
+ $this->_view = $view;
+ }
+ }
+
+ function getView() {
+ return $this->_view;
+ }
+
+ function hasAccessTo($view) {
+ switch($view) {
+ case 'chat':
+ case 'teaser':
+ if($this->isLoggedIn()) {
+ return true;
+ }
+ return false;
+ case 'logs':
+ if($this->isLoggedIn() && ($this->getUserRole() == AJAX_CHAT_ADMIN ||
+ ($this->getConfig('logsUserAccess') &&
+ ($this->getUserRole() == AJAX_CHAT_MODERATOR || $this->getUserRole() == AJAX_CHAT_USER))
+ )) {
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ function login() {
+ // Retrieve valid login user data (from request variables or session data):
+ $userData = $this->getValidLoginUserData();
+
+ if(!$userData) {
+ $this->addInfoMessage('errorInvalidUser');
+ return false;
+ }
+
+ // If the chat is closed, only the admin may login:
+ if(!$this->isChatOpen() && $userData['userRole'] != AJAX_CHAT_ADMIN) {
+ $this->addInfoMessage('errorChatClosed');
+ return false;
+ }
+
+ if(!$this->getConfig('allowGuestLogins') && $userData['userRole'] == AJAX_CHAT_GUEST) {
+ return false;
+ }
+
+ // Check if userID or userName are already listed online:
+ if($this->isUserOnline($userData['userID']) || $this->isUserNameInUse($userData['userName'])) {
+ if($userData['userRole'] == AJAX_CHAT_USER || $userData['userRole'] == AJAX_CHAT_MODERATOR || $userData['userRole'] == AJAX_CHAT_ADMIN) {
+ // Set the registered user inactive and remove the inactive users so the user can be logged in again:
+ $this->setInactive($userData['userID'], $userData['userName']);
+ $this->removeInactive();
+ } else {
+ $this->addInfoMessage('errorUserInUse');
+ return false;
+ }
+ }
+
+ // Check if user is banned:
+ if($userData['userRole'] != AJAX_CHAT_ADMIN && $this->isUserBanned($userData['userName'], $userData['userID'], $_SERVER['REMOTE_ADDR'])) {
+ $this->addInfoMessage('errorBanned');
+ return false;
+ }
+
+ // Check if the max number of users is logged in (not affecting moderators or admins):
+ if(!($userData['userRole'] == AJAX_CHAT_MODERATOR || $userData['userRole'] == AJAX_CHAT_ADMIN) && $this->isMaxUsersLoggedIn()) {
+ $this->addInfoMessage('errorMaxUsersLoggedIn');
+ return false;
+ }
+
+ // Use a new session id (if session has been started by the chat):
+ $this->regenerateSessionID();
+
+ // Log in:
+ $this->setUserID($userData['userID']);
+ $this->setUserName($userData['userName']);
+ $this->setLoginUserName($userData['userName']);
+ $this->setUserRole($userData['userRole']);
+ $this->setLoggedIn(true);
+ $this->setLoginTimeStamp(time());
+
+ // IP Security check variable:
+ $this->setSessionIP($_SERVER['REMOTE_ADDR']);
+
+ // The client authenticates to the socket server using a socketRegistrationID:
+ if($this->getConfig('socketServerEnabled')) {
+ $this->setSocketRegistrationID(
+ md5(uniqid(rand(), true))
+ );
+ }
+
+ // Add userID, userName and userRole to info messages:
+ $this->addInfoMessage($this->getUserID(), 'userID');
+ $this->addInfoMessage($this->getUserName(), 'userName');
+ $this->addInfoMessage($this->getUserRole(), 'userRole');
+
+ // Purge logs:
+ if($this->getConfig('logsPurgeLogs')) {
+ $this->purgeLogs();
+ }
+
+ return true;
+ }
+
+ function chatViewLogin() {
+ $this->setChannel($this->getValidRequestChannelID());
+ $this->addToOnlineList();
+
+ // Add channelID and channelName to info messages:
+ $this->addInfoMessage($this->getChannel(), 'channelID');
+ $this->addInfoMessage($this->getChannelName(), 'channelName');
+
+ // Login message:
+ $text = '/login '.$this->getUserName();
+ $this->insertChatBotMessage(
+ $this->getChannel(),
+ $text,
+ null,
+ 1
+ );
+ }
+
+ function getValidRequestChannelID() {
+ $channelID = $this->getRequestVar('channelID');
+ $channelName = $this->getRequestVar('channelName');
+ // Check the given channelID, or get channelID from channelName:
+ if($channelID === null) {
+ if($channelName !== null) {
+ $channelID = $this->getChannelIDFromChannelName($channelName);
+ // channelName might need encoding conversion:
+ if($channelID === null) {
+ $channelID = $this->getChannelIDFromChannelName(
+ $this->trimChannelName($channelName, $this->getConfig('contentEncoding'))
+ );
+ }
+ }
+ }
+ // Validate the resulting channelID:
+ if(!$this->validateChannel($channelID)) {
+ if($this->getChannel() !== null) {
+ return $this->getChannel();
+ }
+ return $this->getConfig('defaultChannelID');
+ }
+ return $channelID;
+ }
+
+ function initChannel() {
+ $channelID = $this->getRequestVar('channelID');
+ $channelName = $this->getRequestVar('channelName');
+ if($channelID !== null) {
+ $this->switchChannel($this->getChannelNameFromChannelID($channelID));
+ } else if($channelName !== null) {
+ if($this->getChannelIDFromChannelName($channelName) === null) {
+ // channelName might need encoding conversion:
+ $channelName = $this->trimChannelName($channelName, $this->getConfig('contentEncoding'));
+ }
+ $this->switchChannel($channelName);
+ }
+ }
+
+ function logout($type=null) {
+ // Update the socket server authentication for the user:
+ if($this->getConfig('socketServerEnabled')) {
+ $this->updateSocketAuthentication($this->getUserID());
+ }
+ if($this->isUserOnline()) {
+ $this->chatViewLogout($type);
+ }
+ $this->setLoggedIn(false);
+ $this->destroySession();
+
+ // Re-initialize the view:
+ $this->initView();
+ }
+
+ function chatViewLogout($type) {
+ $this->removeFromOnlineList();
+ if($type !== null) {
+ $type = ' '.$type;
+ }
+ // Logout message
+ $text = '/logout '.$this->getUserName().$type;
+ $this->insertChatBotMessage(
+ $this->getChannel(),
+ $text,
+ null,
+ 1
+ );
+ }
+
+ function switchChannel($channelName) {
+ $channelID = $this->getChannelIDFromChannelName($channelName);
+
+ if($channelID !== null && $this->getChannel() == $channelID) {
+ // User is already in the given channel, return:
+ return;
+ }
+
+ // Check if we have a valid channel:
+ if(!$this->validateChannel($channelID)) {
+ // Invalid channel:
+ $text = '/error InvalidChannelName '.$channelName;
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ $text
+ );
+ return;
+ }
+
+ $oldChannel = $this->getChannel();
+
+ $this->setChannel($channelID);
+ $this->updateOnlineList();
+
+ // Channel leave message
+ $text = '/channelLeave '.$this->getUserName();
+ $this->insertChatBotMessage(
+ $oldChannel,
+ $text,
+ null,
+ 1
+ );
+
+ // Channel enter message
+ $text = '/channelEnter '.$this->getUserName();
+ $this->insertChatBotMessage(
+ $this->getChannel(),
+ $text,
+ null,
+ 1
+ );
+
+ $this->addInfoMessage($channelName, 'channelSwitch');
+ $this->addInfoMessage($channelID, 'channelID');
+ $this->_requestVars['lastID'] = 0;
+ }
+
+ function addToOnlineList() {
+ $sql = 'INSERT INTO '.$this->getDataBaseTable('online').'(
+ userID,
+ userName,
+ userRole,
+ channel,
+ dateTime,
+ ip
+ )
+ VALUES (
+ '.$this->db->makeSafe($this->getUserID()).',
+ '.$this->db->makeSafe($this->getUserName()).',
+ '.$this->db->makeSafe($this->getUserRole()).',
+ '.$this->db->makeSafe($this->getChannel()).',
+ NOW(),
+ '.$this->db->makeSafe($this->ipToStorageFormat($_SERVER['REMOTE_ADDR'])).'
+ );';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $this->resetOnlineUsersData();
+ }
+
+ function removeFromOnlineList() {
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('online').'
+ WHERE
+ userID = '.$this->db->makeSafe($this->getUserID()).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $this->removeUserFromOnlineUsersData();
+ }
+
+ function updateOnlineList() {
+ $sql = 'UPDATE
+ '.$this->getDataBaseTable('online').'
+ SET
+ userName = '.$this->db->makeSafe($this->getUserName()).',
+ channel = '.$this->db->makeSafe($this->getChannel()).',
+ dateTime = NOW(),
+ ip = '.$this->db->makeSafe($this->ipToStorageFormat($_SERVER['REMOTE_ADDR'])).'
+ WHERE
+ userID = '.$this->db->makeSafe($this->getUserID()).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $this->resetOnlineUsersData();
+ }
+
+ function initMessageHandling() {
+ // Don't handle messages if we are not in chat view:
+ if($this->getView() != 'chat') {
+ return;
+ }
+
+ // Check if we have been uninvited from a private or restricted channel:
+ if(!$this->validateChannel($this->getChannel())) {
+ // Switch to the default channel:
+ $this->switchChannel($this->getChannelNameFromChannelID($this->getConfig('defaultChannelID')));
+ return;
+ }
+
+ if($this->getRequestVar('text') !== null) {
+ $this->insertMessage($this->getRequestVar('text'));
+ }
+ }
+
+ function insertParsedMessage($text) {
+
+ // If a queryUserName is set, sent all messages as private messages to this userName:
+ if($this->getQueryUserName() !== null && strpos($text, '/') !== 0) {
+ $text = '/msg '.$this->getQueryUserName().' '.$text;
+ }
+
+ // Parse IRC-style commands:
+ if(strpos($text, '/') === 0) {
+ $textParts = explode(' ', $text);
+
+ switch($textParts[0]) {
+
+ // Channel switch:
+ case '/join':
+ $this->insertParsedMessageJoin($textParts);
+ break;
+
+ // Logout:
+ case '/quit':
+ $this->logout();
+ break;
+
+ // Private message:
+ case '/msg':
+ case '/describe':
+ $this->insertParsedMessagePrivMsg($textParts);
+ break;
+
+ // Invitation:
+ case '/invite':
+ $this->insertParsedMessageInvite($textParts);
+ break;
+
+ // Uninvitation:
+ case '/uninvite':
+ $this->insertParsedMessageUninvite($textParts);
+ break;
+
+ // Private messaging:
+ case '/query':
+ $this->insertParsedMessageQuery($textParts);
+ break;
+
+ // Kicking offending users from the chat:
+ case '/kick':
+ $this->insertParsedMessageKick($textParts);
+ break;
+
+ // Listing banned users:
+ case '/bans':
+ $this->insertParsedMessageBans($textParts);
+ break;
+
+ // Unban user (remove from ban list):
+ case '/unban':
+ $this->insertParsedMessageUnban($textParts);
+ break;
+
+ // Describing actions:
+ case '/me':
+ case '/action':
+ $this->insertParsedMessageAction($textParts);
+ break;
+
+
+ // Listing online Users:
+ case '/who':
+ $this->insertParsedMessageWho($textParts);
+ break;
+
+ // Listing available channels:
+ case '/list':
+ $this->insertParsedMessageList($textParts);
+ break;
+
+ // Retrieving the channel of a User:
+ case '/whereis':
+ $this->insertParsedMessageWhereis($textParts);
+ break;
+
+ // Listing information about a User:
+ case '/whois':
+ $this->insertParsedMessageWhois($textParts);
+ break;
+
+ // Rolling dice:
+ case '/roll':
+ $this->insertParsedMessageRoll($textParts);
+ break;
+
+ // Switching userName:
+ case '/nick':
+ $this->insertParsedMessageNick($textParts);
+ break;
+
+ // Custom or unknown command:
+ default:
+ if(!$this->parseCustomCommands($text, $textParts)) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UnknownCommand '.$textParts[0]
+ );
+ }
+ }
+
+ } else {
+ // No command found, just insert the plain message:
+ $this->insertCustomMessage(
+ $this->getUserID(),
+ $this->getUserName(),
+ $this->getUserRole(),
+ $this->getChannel(),
+ $text
+ );
+ }
+ }
+
+ function insertParsedMessageJoin($textParts) {
+ if(count($textParts) == 1) {
+ // join with no arguments is the own private channel, if allowed:
+ if($this->isAllowedToCreatePrivateChannel()) {
+ // Private channels are identified by square brackets:
+ $this->switchChannel($this->getChannelNameFromChannelID($this->getPrivateChannelID()));
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingChannelName'
+ );
+ }
+ } else {
+ $this->switchChannel($textParts[1]);
+ }
+ }
+
+ function insertParsedMessagePrivMsg($textParts) {
+ if($this->isAllowedToSendPrivateMessage()) {
+ if(count($textParts) < 3) {
+ if(count($textParts) == 2) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingText'
+ );
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ }
+ } else {
+ // Get UserID from UserName:
+ $toUserID = $this->getIDFromName($textParts[1]);
+ if($toUserID === null) {
+ if($this->getQueryUserName() !== null) {
+ // Close the current query:
+ $this->insertMessage('/query');
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ }
+ } else {
+ // Insert /privaction command if /describe is used:
+ $command = ($textParts[0] == '/describe') ? '/privaction' : '/privmsg';
+ // Copy of private message to current User:
+ $this->insertCustomMessage(
+ $this->getUserID(),
+ $this->getUserName(),
+ $this->getUserRole(),
+ $this->getPrivateMessageID(),
+ $command.'to '.$textParts[1].' '.implode(' ', array_slice($textParts, 2))
+ );
+ // Private message to requested User:
+ $this->insertCustomMessage(
+ $this->getUserID(),
+ $this->getUserName(),
+ $this->getUserRole(),
+ $this->getPrivateMessageID($toUserID),
+ $command.' '.implode(' ', array_slice($textParts, 2))
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error PrivateMessageNotAllowed'
+ );
+ }
+ }
+
+ function insertParsedMessageInvite($textParts) {
+ if($this->getChannel() == $this->getPrivateChannelID() || in_array($this->getChannel(), $this->getChannels())) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ $toUserID = $this->getIDFromName($textParts[1]);
+ if($toUserID === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // Add the invitation to the database:
+ $this->addInvitation($toUserID);
+ $invitationChannelName = $this->getChannelNameFromChannelID($this->getChannel());
+ // Copy of invitation to current User:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/inviteto '.$textParts[1].' '.$invitationChannelName
+ );
+ // Invitation to requested User:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID($toUserID),
+ '/invite '.$this->getUserName().' '.$invitationChannelName
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error InviteNotAllowed'
+ );
+ }
+ }
+
+ function insertParsedMessageUninvite($textParts) {
+ if($this->getChannel() == $this->getPrivateChannelID() || in_array($this->getChannel(), $this->getChannels())) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ $toUserID = $this->getIDFromName($textParts[1]);
+ if($toUserID === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // Remove the invitation from the database:
+ $this->removeInvitation($toUserID);
+ $invitationChannelName = $this->getChannelNameFromChannelID($this->getChannel());
+ // Copy of uninvitation to current User:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/uninviteto '.$textParts[1].' '.$invitationChannelName
+ );
+ // Uninvitation to requested User:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID($toUserID),
+ '/uninvite '.$this->getUserName().' '.$invitationChannelName
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UninviteNotAllowed'
+ );
+ }
+ }
+
+ function insertParsedMessageQuery($textParts) {
+ if($this->isAllowedToSendPrivateMessage()) {
+ if(count($textParts) == 1) {
+ if($this->getQueryUserName() !== null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/queryClose '.$this->getQueryUserName()
+ );
+ // Close the current query:
+ $this->setQueryUserName(null);
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error NoOpenQuery'
+ );
+ }
+ } else {
+ if($this->getIDFromName($textParts[1]) === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ if($this->getQueryUserName() !== null) {
+ // Close the current query:
+ $this->insertMessage('/query');
+ }
+ // Open a query to the requested user:
+ $this->setQueryUserName($textParts[1]);
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/queryOpen '.$textParts[1]
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error PrivateMessageNotAllowed'
+ );
+ }
+ }
+
+ function insertParsedMessageKick($textParts) {
+ // Only moderators/admins may kick users:
+ if($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ // Get UserID from UserName:
+ $kickUserID = $this->getIDFromName($textParts[1]);
+ if($kickUserID === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // Check the role of the user to kick:
+ $kickUserRole = $this->getRoleFromID($kickUserID);
+ if($kickUserRole == AJAX_CHAT_ADMIN || ($kickUserRole == AJAX_CHAT_MODERATOR && $this->getUserRole() != AJAX_CHAT_ADMIN)) {
+ // Admins and moderators may not be kicked:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error KickNotAllowed '.$textParts[1]
+ );
+ } else {
+ // Kick user and insert message:
+ $channel = $this->getChannelFromID($kickUserID);
+ $banMinutes = (count($textParts) > 2) ? $textParts[2] : null;
+ $this->kickUser($textParts[1], $banMinutes, $kickUserID);
+ // If no channel found, user logged out before he could be kicked
+ if($channel !== null) {
+ $this->insertChatBotMessage(
+ $channel,
+ '/kick '.$textParts[1],
+ null,
+ 1
+ );
+ // Send a copy of the message to the current user, if not in the channel:
+ if($channel != $this->getChannel()) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/kick '.$textParts[1],
+ null,
+ 1
+ );
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error CommandNotAllowed '.$textParts[0]
+ );
+ }
+ }
+
+ function insertParsedMessageBans($textParts) {
+ // Only moderators/admins may see the list of banned users:
+ if($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ $this->removeExpiredBans();
+ $bannedUsers = $this->getBannedUsers();
+ if(count($bannedUsers) > 0) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/bans '.implode(' ', $bannedUsers)
+ );
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/bansEmpty -'
+ );
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error CommandNotAllowed '.$textParts[0]
+ );
+ }
+ }
+
+ function insertParsedMessageUnban($textParts) {
+ // Only moderators/admins may unban users:
+ if($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ $this->removeExpiredBans();
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ if(!in_array($textParts[1], $this->getBannedUsers())) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // Unban user and insert message:
+ $this->unbanUser($textParts[1]);
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/unban '.$textParts[1]
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error CommandNotAllowed '.$textParts[0]
+ );
+ }
+ }
+
+ function insertParsedMessageAction($textParts) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingText'
+ );
+ } else {
+ if($this->getQueryUserName() !== null) {
+ // If we are in query mode, sent the action to the query user:
+ $this->insertMessage('/describe '.$this->getQueryUserName().' '.implode(' ', array_slice($textParts, 1)));
+ } else {
+ $this->insertCustomMessage(
+ $this->getUserID(),
+ $this->getUserName(),
+ $this->getUserRole(),
+ $this->getChannel(),
+ implode(' ', $textParts)
+ );
+ }
+ }
+ }
+
+ function insertParsedMessageWho($textParts) {
+ if(count($textParts) == 1) {
+ if($this->isAllowedToListHiddenUsers()) {
+ // List online users from any channel:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/who '.implode(' ', $this->getOnlineUsers())
+ );
+ } else {
+ // Get online users for all accessible channels:
+ $channels = $this->getChannels();
+ // Add the own private channel if allowed:
+ if($this->isAllowedToCreatePrivateChannel()) {
+ array_push($channels, $this->getPrivateChannelID());
+ }
+ // Add the invitation channels:
+ foreach($this->getInvitations() as $channelID) {
+ if(!in_array($channelID, $channels)) {
+ array_push($channels, $channelID);
+ }
+ }
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/who '.implode(' ', $this->getOnlineUsers($channels))
+ );
+ }
+ } else {
+ $channelName = $textParts[1];
+ $channelID = $this->getChannelIDFromChannelName($channelName);
+ if(!$this->validateChannel($channelID)) {
+ // Invalid channel:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error InvalidChannelName '.$channelName
+ );
+ } else {
+ // Get online users for the given channel:
+ $onlineUsers = $this->getOnlineUsers(array($channelID));
+ if(count($onlineUsers) > 0) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/whoChannel '.$channelName.' '.implode(' ', $onlineUsers)
+ );
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/whoEmpty -'
+ );
+ }
+ }
+ }
+ }
+
+ function insertParsedMessageList($textParts) {
+ // Get the names of all accessible channels:
+ $channelNames = $this->getChannelNames();
+ // Add the own private channel, if allowed:
+ if($this->isAllowedToCreatePrivateChannel()) {
+ array_push($channelNames, $this->getPrivateChannelName());
+ }
+ // Add the invitation channels:
+ foreach($this->getInvitations() as $channelID) {
+ $channelName = $this->getChannelNameFromChannelID($channelID);
+ if($channelName !== null && !in_array($channelName, $channelNames)) {
+ array_push($channelNames, $channelName);
+ }
+ }
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/list '.implode(' ', $channelNames)
+ );
+ }
+
+ function insertParsedMessageWhereis($textParts) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ // Get UserID from UserName:
+ $whereisUserID = $this->getIDFromName($textParts[1]);
+ if($whereisUserID === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ $channelID = $this->getChannelFromID($whereisUserID);
+ if($this->validateChannel($channelID)) {
+ $channelName = $this->getChannelNameFromChannelID($channelID);
+ } else {
+ $channelName = null;
+ }
+ if($channelName === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // List user information:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/whereis '.$textParts[1].' '.$channelName
+ );
+ }
+ }
+ }
+ }
+
+ function insertParsedMessageWhois($textParts) {
+ // Only moderators/admins:
+ if($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ // Get UserID from UserName:
+ $whoisUserID = $this->getIDFromName($textParts[1]);
+ if($whoisUserID === null) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameNotFound '.$textParts[1]
+ );
+ } else {
+ // List user information:
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/whois '.$textParts[1].' '.$this->getIPFromID($whoisUserID)
+ );
+ }
+ }
+ } else {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error CommandNotAllowed '.$textParts[0]
+ );
+ }
+ }
+
+ function insertParsedMessageRoll($textParts) {
+ if(count($textParts) == 1) {
+ // default is one d6:
+ $text = '/roll '.$this->getUserName().' 1d6 '.$this->rollDice(6);
+ } else {
+ $diceParts = explode('d', $textParts[1]);
+ if(count($diceParts) == 2) {
+ $number = (int)$diceParts[0];
+ $sides = (int)$diceParts[1];
+
+ // Dice number must be an integer between 1 and 100, else roll only one:
+ $number = ($number > 0 && $number <= 100) ? $number : 1;
+
+ // Sides must be an integer between 1 and 100, else take 6:
+ $sides = ($sides > 0 && $sides <= 100) ? $sides : 6;
+
+ $text = '/roll '.$this->getUserName().' '.$number.'d'.$sides.' ';
+ for($i=0; $i<$number; $i++) {
+ if($i != 0)
+ $text .= ',';
+ $text .= $this->rollDice($sides);
+ }
+ } else {
+ // if dice syntax is invalid, roll one d6:
+ $text = '/roll '.$this->getUserName().' 1d6 '.$this->rollDice(6);
+ }
+ }
+ $this->insertChatBotMessage(
+ $this->getChannel(),
+ $text
+ );
+ }
+
+ function insertParsedMessageNick($textParts) {
+ if(!$this->getConfig('allowNickChange') ||
+ (!$this->getConfig('allowGuestUserName') && $this->getUserRole() == AJAX_CHAT_GUEST)) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error CommandNotAllowed '.$textParts[0]
+ );
+ } else if(count($textParts) == 1) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MissingUserName'
+ );
+ } else {
+ $newUserName = implode(' ', array_slice($textParts, 1));
+ if($newUserName == $this->getLoginUserName()) {
+ // Allow the user to regain the original login userName:
+ $prefix = '';
+ $suffix = '';
+ } else if($this->getUserRole() == AJAX_CHAT_GUEST) {
+ $prefix = $this->getConfig('guestUserPrefix');
+ $suffix = $this->getConfig('guestUserSuffix');
+ } else {
+ $prefix = $this->getConfig('changedNickPrefix');
+ $suffix = $this->getConfig('changedNickSuffix');
+ }
+ $maxLength = $this->getConfig('userNameMaxLength')
+ - $this->stringLength($prefix)
+ - $this->stringLength($suffix);
+ $newUserName = $this->trimString($newUserName, 'UTF-8', $maxLength, true);
+ if(!$newUserName) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error InvalidUserName'
+ );
+ } else {
+ $newUserName = $prefix.$newUserName.$suffix;
+ if($this->isUserNameInUse($newUserName)) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error UserNameInUse'
+ );
+ } else {
+ $oldUserName = $this->getUserName();
+ $this->setUserName($newUserName);
+ $this->updateOnlineList();
+ // Add info message to update the client-side stored userName:
+ $this->addInfoMessage($this->getUserName(), 'userName');
+ $this->insertChatBotMessage(
+ $this->getChannel(),
+ '/nick '.$oldUserName.' '.$newUserName,
+ null,
+ 2
+ );
+ }
+ }
+ }
+ }
+
+ function insertMessage($text) {
+ if(!$this->isAllowedToWriteMessage())
+ return;
+
+ if(!$this->floodControl())
+ return;
+
+ $text = $this->trimMessageText($text);
+ if($text == '')
+ return;
+
+ if(!$this->onNewMessage($text))
+ return;
+
+ $text = $this->replaceCustomText($text);
+
+ $this->insertParsedMessage($text);
+ }
+
+ function deleteMessage($messageID) {
+ // Retrieve the channel of the given message:
+ $sql = 'SELECT
+ channel
+ FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ id='.$this->db->makeSafe($messageID).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $row = $result->fetch();
+
+ if($row['channel'] !== null) {
+ $channel = $row['channel'];
+
+ if($this->getUserRole() == AJAX_CHAT_ADMIN) {
+ $condition = '';
+ } else if($this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ $condition = ' AND
+ NOT (userRole='.$this->db->makeSafe(AJAX_CHAT_ADMIN).')
+ AND
+ NOT (userRole='.$this->db->makeSafe(AJAX_CHAT_CHATBOT).')';
+ } else if($this->getUserRole() == AJAX_CHAT_USER && $this->getConfig('allowUserMessageDelete')) {
+ $condition = 'AND
+ (
+ userID='.$this->db->makeSafe($this->getUserID()).'
+ OR
+ (
+ channel = '.$this->db->makeSafe($this->getPrivateMessageID()).'
+ OR
+ channel = '.$this->db->makeSafe($this->getPrivateChannelID()).'
+ )
+ AND
+ NOT (userRole='.$this->db->makeSafe(AJAX_CHAT_ADMIN).')
+ AND
+ NOT (userRole='.$this->db->makeSafe(AJAX_CHAT_CHATBOT).')
+ )';
+ } else {
+ return false;
+ }
+
+ // Remove given message from the database:
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ id='.$this->db->makeSafe($messageID).'
+ '.$condition.';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ if($result->affectedRows() == 1) {
+ // Insert a deletion command to remove the message from the clients chatlists:
+ $this->insertChatBotMessage($channel, '/delete '.$messageID);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function floodControl() {
+ // Moderators and Admins need no flood control:
+ if($this->getUserRole() == AJAX_CHAT_MODERATOR || $this->getUserRole() == AJAX_CHAT_ADMIN) {
+ return true;
+ }
+ $time = time();
+ // Check the time of the last inserted message:
+ if($this->getInsertedMessagesRateTimeStamp()+60 < $time) {
+ $this->setInsertedMessagesRateTimeStamp($time);
+ $this->setInsertedMessagesRate(1);
+ } else {
+ // Increase the inserted messages rate:
+ $rate = $this->getInsertedMessagesRate()+1;
+ $this->setInsertedMessagesRate($rate);
+ // Check if message rate is too high:
+ if($rate > $this->getConfig('maxMessageRate')) {
+ $this->insertChatBotMessage(
+ $this->getPrivateMessageID(),
+ '/error MaxMessageRate'
+ );
+ // Return false so the message is not inserted:
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function isAllowedToWriteMessage() {
+ if($this->getUserRole() != AJAX_CHAT_GUEST)
+ return true;
+ if($this->getConfig('allowGuestWrite'))
+ return true;
+ return false;
+ }
+
+ function insertChatBotMessage($channelID, $messageText, $ip=null, $mode=0) {
+ $this->insertCustomMessage(
+ $this->getConfig('chatBotID'),
+ $this->getConfig('chatBotName'),
+ AJAX_CHAT_CHATBOT,
+ $channelID,
+ $messageText,
+ $ip,
+ $mode
+ );
+ }
+
+ function insertCustomMessage($userID, $userName, $userRole, $channelID, $text, $ip=null, $mode=0) {
+ // The $mode parameter is used for socket updates:
+ // 0 = normal messages
+ // 1 = channel messages (e.g. login/logout, channel enter/leave, kick)
+ // 2 = messages with online user updates (nick)
+
+ $ip = $ip ? $ip : $_SERVER['REMOTE_ADDR'];
+
+ $sql = 'INSERT INTO '.$this->getDataBaseTable('messages').'(
+ userID,
+ userName,
+ userRole,
+ channel,
+ dateTime,
+ ip,
+ text
+ )
+ VALUES (
+ '.$this->db->makeSafe($userID).',
+ '.$this->db->makeSafe($userName).',
+ '.$this->db->makeSafe($userRole).',
+ '.$this->db->makeSafe($channelID).',
+ NOW(),
+ '.$this->db->makeSafe($this->ipToStorageFormat($ip)).',
+ '.$this->db->makeSafe($text).'
+ );';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ if($this->getConfig('socketServerEnabled')) {
+ $this->sendSocketMessage(
+ $this->getSocketBroadcastMessage(
+ $this->db->getLastInsertedID(),
+ time(),
+ $userID,
+ $userName,
+ $userRole,
+ $channelID,
+ $text,
+ $mode
+ )
+ );
+ }
+ }
+
+ function getSocketBroadcastMessage(
+ $messageID,
+ $timeStamp,
+ $userID,
+ $userName,
+ $userRole,
+ $channelID,
+ $text,
+ $mode
+ ) {
+ // The $mode parameter:
+ // 0 = normal messages
+ // 1 = channel messages (e.g. login/logout, channel enter/leave, kick)
+ // 2 = messages with online user updates (nick)
+
+ // Get the message XML content:
+ $xml = '<root chatID="'.$this->getConfig('socketServerChatID').'" channelID="'.$channelID.'" mode="'.$mode.'">';
+ if($mode) {
+ // Add the list of online users if the user list has been updated ($mode > 0):
+ $xml .= $this->getChatViewOnlineUsersXML(array($channelID));
+ }
+ if($mode != 1 || $this->getConfig('showChannelMessages')) {
+ $xml .= '<messages>';
+ $xml .= $this->getChatViewMessageXML(
+ $messageID,
+ $timeStamp,
+ $userID,
+ $userName,
+ $userRole,
+ $channelID,
+ $text
+ );
+ $xml .= '</messages>';
+ }
+ $xml .= '</root>';
+ return $xml;
+ }
+
+ function sendSocketMessage($message) {
+ // Open a TCP socket connection to the socket server:
+ if($socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) {
+ if(@socket_connect($socket, $this->getConfig('socketServerIP'), $this->getConfig('socketServerPort'))) {
+ // Append a null-byte to the string as EOL (End Of Line) character
+ // which is required by Flash XML socket communication:
+ $message .= "\0";
+ @socket_write(
+ $socket,
+ $message,
+ strlen($message) // Using strlen to count the bytes instead of the number of UTF-8 characters
+ );
+ }
+ @socket_close($socket);
+ }
+ }
+
+ function updateSocketAuthentication($userID, $socketRegistrationID=null, $channels=null) {
+ // If no $socketRegistrationID or no $channels are given the authentication is removed for the given user:
+ $authentication = '<authenticate chatID="'.$this->getConfig('socketServerChatID').'" userID="'.$userID.'" regID="'.$socketRegistrationID.'">';
+ if($channels) {
+ foreach($channels as $channelID) {
+ $authentication .= '<channel id="'.$channelID.'"/>';
+ }
+ }
+ $authentication .= '</authenticate>';
+ $this->sendSocketMessage($authentication);
+ }
+
+ function setSocketRegistrationID($value) {
+ $this->setSessionVar('SocketRegistrationID', $value);
+ }
+
+ function getSocketRegistrationID() {
+ return $this->getSessionVar('SocketRegistrationID');
+ }
+
+ function rollDice($sides) {
+ // seed with microseconds since last "whole" second:
+ mt_srand((double)microtime()*1000000);
+
+ return mt_rand(1, $sides);
+ }
+
+ function kickUser($userName, $banMinutes=null, $userID=null) {
+ if($userID === null) {
+ $userID = $this->getIDFromName($userName);
+ }
+ if($userID === null) {
+ return;
+ }
+
+ $banMinutes = $banMinutes ? $banMinutes : $this->getConfig('defaultBanTime');
+
+ if($banMinutes) {
+ // Ban User for the given time in minutes:
+ $this->banUser($userName, $banMinutes, $userID);
+ }
+
+ // Remove given User from online list:
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('online').'
+ WHERE
+ userID = '.$this->db->makeSafe($userID).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ // Update the socket server authentication for the kicked user:
+ if($this->getConfig('socketServerEnabled')) {
+ $this->updateSocketAuthentication($userID);
+ }
+
+ $this->removeUserFromOnlineUsersData($userID);
+ }
+
+ function getBannedUsersData($key=null, $value=null) {
+ if($this->_bannedUsersData === null) {
+ $this->_bannedUsersData = array();
+
+ $sql = 'SELECT
+ userID,
+ userName,
+ ip
+ FROM
+ '.$this->getDataBaseTable('bans').'
+ WHERE
+ NOW() < dateTime;';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ while($row = $result->fetch()) {
+ $row['ip'] = $this->ipFromStorageFormat($row['ip']);
+ array_push($this->_bannedUsersData, $row);
+ }
+
+ $result->free();
+ }
+
+ if($key) {
+ $bannedUsersData = array();
+ foreach($this->_bannedUsersData as $bannedUserData) {
+ if(!isset($bannedUserData[$key])) {
+ return $bannedUsersData;
+ }
+ if($value) {
+ if($bannedUserData[$key] == $value) {
+ array_push($bannedUsersData, $bannedUserData);
+ } else {
+ continue;
+ }
+ } else {
+ array_push($bannedUsersData, $bannedUserData[$key]);
+ }
+ }
+ return $bannedUsersData;
+ }
+
+ return $this->_bannedUsersData;
+ }
+
+ function getBannedUsers() {
+ return $this->getBannedUsersData('userName');
+ }
+
+ function banUser($userName, $banMinutes=null, $userID=null) {
+ if($userID === null) {
+ $userID = $this->getIDFromName($userName);
+ }
+ $ip = $this->getIPFromID($userID);
+ if(!$ip || $userID === null) {
+ return;
+ }
+
+ // Remove expired bans:
+ $this->removeExpiredBans();
+
+ $banMinutes = (int)$banMinutes;
+ if(!$banMinutes) {
+ // If banMinutes is not a valid integer, use the defaultBanTime:
+ $banMinutes = $this->getConfig('defaultBanTime');
+ }
+
+ $sql = 'INSERT INTO '.$this->getDataBaseTable('bans').'(
+ userID,
+ userName,
+ dateTime,
+ ip
+ )
+ VALUES (
+ '.$this->db->makeSafe($userID).',
+ '.$this->db->makeSafe($userName).',
+ DATE_ADD(NOW(), interval '.$this->db->makeSafe($banMinutes).' MINUTE),
+ '.$this->db->makeSafe($this->ipToStorageFormat($ip)).'
+ );';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function unbanUser($userName) {
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('bans').'
+ WHERE
+ userName = '.$this->db->makeSafe($userName).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function removeExpiredBans() {
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('bans').'
+ WHERE
+ dateTime < NOW();';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function setInactive($userID, $userName=null) {
+ $condition = 'userID='.$this->db->makeSafe($userID);
+ if($userName !== null) {
+ $condition .= ' OR userName='.$this->db->makeSafe($userName);
+ }
+ $sql = 'UPDATE
+ '.$this->getDataBaseTable('online').'
+ SET
+ dateTime = DATE_SUB(NOW(), interval '.(intval($this->getConfig('inactiveTimeout'))+1).' MINUTE)
+ WHERE
+ '.$condition.';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $this->resetOnlineUsersData();
+ }
+
+ function removeInactive() {
+ $sql = 'SELECT
+ userID,
+ userName,
+ channel
+ FROM
+ '.$this->getDataBaseTable('online').'
+ WHERE
+ NOW() > DATE_ADD(dateTime, interval '.$this->getConfig('inactiveTimeout').' MINUTE);';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ if($result->numRows() > 0) {
+ $condition = '';
+ while($row = $result->fetch()) {
+ if(!empty($condition))
+ $condition .= ' OR ';
+ // Add userID to condition for removal:
+ $condition .= 'userID='.$this->db->makeSafe($row['userID']);
+
+ // Update the socket server authentication for the kicked user:
+ if($this->getConfig('socketServerEnabled')) {
+ $this->updateSocketAuthentication($row['userID']);
+ }
+
+ $this->removeUserFromOnlineUsersData($row['userID']);
+
+ // Insert logout timeout message:
+ $text = '/logout '.$row['userName'].' Timeout';
+ $this->insertChatBotMessage(
+ $row['channel'],
+ $text,
+ null,
+ 1
+ );
+ }
+
+ $result->free();
+
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('online').'
+ WHERE
+ '.$condition.';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+ }
+
+ function updateOnlineStatus() {
+ // Update online status every 50 seconds (this allows update requests to be in time):
+ if(!$this->getStatusUpdateTimeStamp() || ((time() - $this->getStatusUpdateTimeStamp()) > 50)) {
+ $this->updateOnlineList();
+ $this->setStatusUpdateTimeStamp(time());
+ }
+ }
+
+ function checkAndRemoveInactive() {
+ // Remove inactive users every inactiveCheckInterval:
+ if(!$this->getInactiveCheckTimeStamp() || ((time() - $this->getInactiveCheckTimeStamp()) > $this->getConfig('inactiveCheckInterval')*60)) {
+ $this->removeInactive();
+ $this->setInactiveCheckTimeStamp(time());
+ }
+ }
+
+ function sendXMLMessages() {
+ $httpHeader = new AJAXChatHTTPHeader('UTF-8', 'text/xml');
+
+ // Send HTTP header:
+ $httpHeader->send();
+
+ // Output XML messages:
+ echo $this->getXMLMessages();
+ }
+
+ function getXMLMessages() {
+ switch($this->getView()) {
+ case 'chat':
+ return $this->getChatViewXMLMessages();
+ case 'teaser':
+ return $this->getTeaserViewXMLMessages();
+ case 'logs':
+ return $this->getLogsViewXMLMessages();
+ default:
+ return $this->getLogoutXMLMessage();
+ }
+ }
+
+ function getMessageCondition() {
+ $condition = 'id > '.$this->db->makeSafe($this->getRequestVar('lastID')).'
+ AND (
+ channel = '.$this->db->makeSafe($this->getChannel()).'
+ OR
+ channel = '.$this->db->makeSafe($this->getPrivateMessageID()).'
+ )
+ AND
+ ';
+ if($this->getConfig('requestMessagesPriorChannelEnter') ||
+ ($this->getConfig('requestMessagesPriorChannelEnterList') && in_array($this->getChannel(), $this->getConfig('requestMessagesPriorChannelEnterList')))) {
+ $condition .= 'NOW() < DATE_ADD(dateTime, interval '.$this->getConfig('requestMessagesTimeDiff').' HOUR)';
+ } else {
+ $condition .= 'dateTime >= FROM_UNIXTIME(' . $this->getChannelEnterTimeStamp() . ')';
+ }
+ return $condition;
+ }
+
+ function getMessageFilter() {
+ $filterChannelMessages = '';
+ if(!$this->getConfig('showChannelMessages') || $this->getRequestVar('shoutbox')) {
+ $filterChannelMessages = ' AND NOT (
+ text LIKE (\'/login%\')
+ OR
+ text LIKE (\'/logout%\')
+ OR
+ text LIKE (\'/channelEnter%\')
+ OR
+ text LIKE (\'/channelLeave%\')
+ OR
+ text LIKE (\'/kick%\')
+ )';
+ }
+ return $filterChannelMessages;
+ }
+
+ function getInfoMessagesXML() {
+ $xml = '<infos>';
+ // Go through the info messages:
+ foreach($this->getInfoMessages() as $type=>$infoArray) {
+ foreach($infoArray as $info) {
+ $xml .= '<info type="'.$type.'">';
+ $xml .= '<![CDATA['.$this->encodeSpecialChars($info).']]>';
+ $xml .= '</info>';
+ }
+ }
+ $xml .= '</infos>';
+ return $xml;
+ }
+
+ function getChatViewOnlineUsersXML($channelIDs) {
+ // Get the online users for the given channels:
+ $onlineUsersData = $this->getOnlineUsersData($channelIDs);
+ $xml = '<users>';
+ foreach($onlineUsersData as $onlineUserData) {
+ $xml .= '<user';
+ $xml .= ' userID="'.$onlineUserData['userID'].'"';
+ $xml .= ' userRole="'.$onlineUserData['userRole'].'"';
+ $xml .= ' channelID="'.$onlineUserData['channel'].'"';
+ $xml .= '>';
+ $xml .= '<![CDATA['.$this->encodeSpecialChars($onlineUserData['userName']).']]>';
+ $xml .= '</user>';
+ }
+ $xml .= '</users>';
+ return $xml;
+ }
+
+ function getLogoutXMLMessage() {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<root>';
+ $xml .= '<infos>';
+ $xml .= '<info type="logout">';
+ $xml .= '<![CDATA['.$this->encodeSpecialChars($this->getConfig('logoutData')).']]>';
+ $xml .= '</info>';
+ $xml .= '</infos>';
+ $xml .= '</root>';
+ return $xml;
+ }
+
+ function getChatViewMessageXML(
+ $messageID,
+ $timeStamp,
+ $userID,
+ $userName,
+ $userRole,
+ $channelID,
+ $text
+ ) {
+ $message = '<message';
+ $message .= ' id="'.$messageID.'"';
+ $message .= ' dateTime="'.date('r', $timeStamp).'"';
+ $message .= ' userID="'.$userID.'"';
+ $message .= ' userRole="'.$userRole.'"';
+ $message .= ' channelID="'.$channelID.'"';
+ $message .= '>';
+ $message .= '<username><![CDATA['.$this->encodeSpecialChars($userName).']]></username>';
+ $message .= '<text><![CDATA['.$this->encodeSpecialChars($text).']]></text>';
+ $message .= '</message>';
+ return $message;
+ }
+
+ function getChatViewMessagesXML() {
+ // Get the last messages in descending order (this optimises the LIMIT usage):
+ $sql = 'SELECT
+ id,
+ userID,
+ userName,
+ userRole,
+ channel AS channelID,
+ UNIX_TIMESTAMP(dateTime) AS timeStamp,
+ text
+ FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ '.$this->getMessageCondition().'
+ '.$this->getMessageFilter().'
+ ORDER BY
+ id
+ DESC
+ LIMIT '.$this->getConfig('requestMessagesLimit').';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $messages = '';
+
+ // Add the messages in reverse order so it is ascending again:
+ while($row = $result->fetch()) {
+ $message = $this->getChatViewMessageXML(
+ $row['id'],
+ $row['timeStamp'],
+ $row['userID'],
+ $row['userName'],
+ $row['userRole'],
+ $row['channelID'],
+ $row['text']
+ );
+ $messages = $message.$messages;
+ }
+ $result->free();
+
+ $messages = '<messages>'.$messages.'</messages>';
+ return $messages;
+ }
+
+ function getChatViewXMLMessages() {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<root>';
+ $xml .= $this->getInfoMessagesXML();
+ $xml .= $this->getChatViewOnlineUsersXML(array($this->getChannel()));
+ $xml .= $this->getChatViewMessagesXML();
+ $xml .= '</root>';
+ return $xml;
+ }
+
+ function getTeaserMessageCondition() {
+ $channelID = $this->getValidRequestChannelID();
+ $condition = 'channel = '.$this->db->makeSafe($channelID).'
+ AND
+ ';
+ if($this->getConfig('requestMessagesPriorChannelEnter') ||
+ ($this->getConfig('requestMessagesPriorChannelEnterList') && in_array($channelID, $this->getConfig('requestMessagesPriorChannelEnterList')))) {
+ $condition .= 'NOW() < DATE_ADD(dateTime, interval '.$this->getConfig('requestMessagesTimeDiff').' HOUR)';
+ } else {
+ // Teaser content may not be shown for this channel:
+ $condition .= '0 = 1';
+ }
+ return $condition;
+ }
+
+ function getTeaserViewMessagesXML() {
+ // Get the last messages in descending order (this optimises the LIMIT usage):
+ $sql = 'SELECT
+ id,
+ userID,
+ userName,
+ userRole,
+ channel AS channelID,
+ UNIX_TIMESTAMP(dateTime) AS timeStamp,
+ text
+ FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ '.$this->getTeaserMessageCondition().'
+ '.$this->getMessageFilter().'
+ ORDER BY
+ id
+ DESC
+ LIMIT '.$this->getConfig('requestMessagesLimit').';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $messages = '';
+
+ // Add the messages in reverse order so it is ascending again:
+ while($row = $result->fetch()) {
+ $message = '';
+ $message .= '<message';
+ $message .= ' id="'.$row['id'].'"';
+ $message .= ' dateTime="'.date('r', $row['timeStamp']).'"';
+ $message .= ' userID="'.$row['userID'].'"';
+ $message .= ' userRole="'.$row['userRole'].'"';
+ $message .= ' channelID="'.$row['channelID'].'"';
+ $message .= '>';
+ $message .= '<username><![CDATA['.$this->encodeSpecialChars($row['userName']).']]></username>';
+ $message .= '<text><![CDATA['.$this->encodeSpecialChars($row['text']).']]></text>';
+ $message .= '</message>';
+ $messages = $message.$messages;
+ }
+ $result->free();
+
+ $messages = '<messages>'.$messages.'</messages>';
+ return $messages;
+ }
+
+ function getTeaserViewXMLMessages() {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<root>';
+ $xml .= $this->getInfoMessagesXML();
+ $xml .= $this->getTeaserViewMessagesXML();
+ $xml .= '</root>';
+ return $xml;
+ }
+
+ function getLogsViewCondition() {
+ $condition = 'id > '.$this->db->makeSafe($this->getRequestVar('lastID'));
+
+ // Check the channel condition:
+ switch($this->getRequestVar('channelID')) {
+ case '-3':
+ // Just display messages from all accessible channels
+ if($this->getUserRole() != AJAX_CHAT_ADMIN) {
+ $condition .= ' AND (channel = '.$this->db->makeSafe($this->getPrivateMessageID());
+ $condition .= ' OR channel = '.$this->db->makeSafe($this->getPrivateChannelID());
+ foreach($this->getChannels() as $channel) {
+ if($this->getConfig('logsUserAccessChannelList') && !in_array($channel, $this->getConfig('logsUserAccessChannelList'))) {
+ continue;
+ }
+ $condition .= ' OR channel = '.$this->db->makeSafe($channel);
+ }
+ $condition .= ')';
+ }
+ break;
+ case '-2':
+ if($this->getUserRole() != AJAX_CHAT_ADMIN) {
+ $condition .= ' AND channel = '.($this->getPrivateMessageID());
+ } else {
+ $condition .= ' AND channel > '.($this->getConfig('privateMessageDiff')-1);
+ }
+ break;
+ case '-1':
+ if($this->getUserRole() != AJAX_CHAT_ADMIN) {
+ $condition .= ' AND channel = '.($this->getPrivateChannelID());
+ } else {
+ $condition .= ' AND (channel > '.($this->getConfig('privateChannelDiff')-1).' AND channel < '.($this->getConfig('privateMessageDiff')).')';
+ }
+ break;
+ default:
+ if(($this->getUserRole() == AJAX_CHAT_ADMIN || !$this->getConfig('logsUserAccessChannelList') || in_array($this->getRequestVar('channelID'), $this->getConfig('logsUserAccessChannelList')))
+ && $this->validateChannel($this->getRequestVar('channelID'))) {
+ $condition .= ' AND channel = '.$this->db->makeSafe($this->getRequestVar('channelID'));
+ } else {
+ // No valid channel:
+ $condition .= ' AND 0 = 1';
+ }
+ }
+
+ // Check the period condition:
+ $hour = ($this->getRequestVar('hour') === null || $this->getRequestVar('hour') > 23 || $this->getRequestVar('hour') < 0) ? null : $this->getRequestVar('hour');
+ $day = ($this->getRequestVar('day') === null || $this->getRequestVar('day') > 31 || $this->getRequestVar('day') < 1) ? null : $this->getRequestVar('day');
+ $month = ($this->getRequestVar('month') === null || $this->getRequestVar('month') > 12 || $this->getRequestVar('month') < 1) ? null : $this->getRequestVar('month');
+ $year = ($this->getRequestVar('year') === null || $this->getRequestVar('year') > date('Y') || $this->getRequestVar('year') < $this->getConfig('logsFirstYear')) ? null : $this->getRequestVar('year');
+
+ // If a time (hour) is given but no date (year, month, day), use the current date:
+ if($hour !== null) {
+ if($day === null)
+ $day = date('j');
+ if($month === null)
+ $month = date('n');
+ if($year === null)
+ $year = date('Y');
+ }
+
+ if($year === null) {
+ // No year given, so no period condition
+ } else if($month === null) {
+ // Define the given year as period:
+ $periodStart = mktime(0, 0, 0, 1, 1, $year);
+ // The last day in a month can be expressed by using 0 for the day of the next month:
+ $periodEnd = mktime(23, 59, 59, 13, 0, $year);
+ } else if($day === null) {
+ // Define the given month as period:
+ $periodStart = mktime(0, 0, 0, $month, 1, $year);
+ // The last day in a month can be expressed by using 0 for the day of the next month:
+ $periodEnd = mktime(23, 59, 59, $month+1, 0, $year);
+ } else if($hour === null){
+ // Define the given day as period:
+ $periodStart = mktime(0, 0, 0, $month, $day, $year);
+ $periodEnd = mktime(23, 59, 59, $month, $day, $year);
+ } else {
+ // Define the given hour as period:
+ $periodStart = mktime($hour, 0, 0, $month, $day, $year);
+ $periodEnd = mktime($hour, 59, 59, $month, $day, $year);
+ }
+
+ if(isset($periodStart))
+ $condition .= ' AND dateTime > \''.date('Y-m-d H:i:s', $periodStart).'\' AND dateTime <= \''.date('Y-m-d H:i:s', $periodEnd).'\'';
+
+ // Check the search condition:
+ if($this->getRequestVar('search')) {
+ if(($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) && strpos($this->getRequestVar('search'), 'ip=') === 0) {
+ // Search for messages with the given IP:
+ $ip = substr($this->getRequestVar('search'), 3);
+ $condition .= ' AND (ip = '.$this->db->makeSafe($this->ipToStorageFormat($ip)).')';
+ } else if(strpos($this->getRequestVar('search'), 'userID=') === 0) {
+ // Search for messages with the given userID:
+ $userID = substr($this->getRequestVar('search'), 7);
+ $condition .= ' AND (userID = '.$this->db->makeSafe($userID).')';
+ } else {
+ // Use the search value as regular expression on message text and username:
+ $condition .= ' AND (userName REGEXP '.$this->db->makeSafe($this->getRequestVar('search')).' OR text REGEXP '.$this->db->makeSafe($this->getRequestVar('search')).')';
+ }
+ }
+
+ // If no period or search condition is given, just monitor the last messages on the given channel:
+ if(!isset($periodStart) && !$this->getRequestVar('search')) {
+ $condition .= ' AND NOW() < DATE_ADD(dateTime, interval '.$this->getConfig('logsRequestMessagesTimeDiff').' HOUR)';
+ }
+
+ return $condition;
+ }
+
+ function getLogsViewMessagesXML() {
+ $sql = 'SELECT
+ id,
+ userID,
+ userName,
+ userRole,
+ channel AS channelID,
+ UNIX_TIMESTAMP(dateTime) AS timeStamp,
+ ip,
+ text
+ FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ '.$this->getLogsViewCondition().'
+ ORDER BY
+ id
+ LIMIT '.$this->getConfig('logsRequestMessagesLimit').';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ $xml = '<messages>';
+ while($row = $result->fetch()) {
+ $xml .= '<message';
+ $xml .= ' id="'.$row['id'].'"';
+ $xml .= ' dateTime="'.date('r', $row['timeStamp']).'"';
+ $xml .= ' userID="'.$row['userID'].'"';
+ $xml .= ' userRole="'.$row['userRole'].'"';
+ $xml .= ' channelID="'.$row['channelID'].'"';
+ if($this->getUserRole() == AJAX_CHAT_ADMIN || $this->getUserRole() == AJAX_CHAT_MODERATOR) {
+ $xml .= ' ip="'.$this->ipFromStorageFormat($row['ip']).'"';
+ }
+ $xml .= '>';
+ $xml .= '<username><![CDATA['.$this->encodeSpecialChars($row['userName']).']]></username>';
+ $xml .= '<text><![CDATA['.$this->encodeSpecialChars($row['text']).']]></text>';
+ $xml .= '</message>';
+ }
+ $result->free();
+
+ $xml .= '</messages>';
+
+ return $xml;
+ }
+
+ function getLogsViewXMLMessages() {
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>';
+ $xml .= '<root>';
+ $xml .= $this->getInfoMessagesXML();
+ $xml .= $this->getLogsViewMessagesXML();
+ $xml .= '</root>';
+ return $xml;
+ }
+
+ function purgeLogs() {
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('messages').'
+ WHERE
+ dateTime < DATE_SUB(NOW(), interval '.$this->getConfig('logsPurgeTimeDiff').' DAY);';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function getInfoMessages($type=null) {
+ if(!isset($this->_infoMessages)) {
+ $this->_infoMessages = array();
+ }
+ if($type) {
+ if(!isset($this->_infoMessages[$type])) {
+ $this->_infoMessages[$type] = array();
+ }
+ return $this->_infoMessages[$type];
+ } else {
+ return $this->_infoMessages;
+ }
+ }
+
+ function addInfoMessage($info, $type='error') {
+ if(!isset($this->_infoMessages)) {
+ $this->_infoMessages = array();
+ }
+ if(!isset($this->_infoMessages[$type])) {
+ $this->_infoMessages[$type] = array();
+ }
+ if(!in_array($info, $this->_infoMessages[$type])) {
+ array_push($this->_infoMessages[$type], $info);
+ }
+ }
+
+ function getRequestVars() {
+ return $this->_requestVars;
+ }
+
+ function getRequestVar($key) {
+ if($this->_requestVars && isset($this->_requestVars[$key])) {
+ return $this->_requestVars[$key];
+ }
+ return null;
+ }
+
+ function setRequestVar($key, $value) {
+ if(!$this->_requestVars) {
+ $this->_requestVars = array();
+ }
+ $this->_requestVars[$key] = $value;
+ }
+
+ function getOnlineUsersData($channelIDs=null, $key=null, $value=null) {
+ if($this->_onlineUsersData === null) {
+ $this->_onlineUsersData = array();
+
+ $sql = 'SELECT
+ userID,
+ userName,
+ userRole,
+ channel,
+ UNIX_TIMESTAMP(dateTime) AS timeStamp,
+ ip
+ FROM
+ '.$this->getDataBaseTable('online').'
+ ORDER BY
+ userName;';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ while($row = $result->fetch()) {
+ $row['ip'] = $this->ipFromStorageFormat($row['ip']);
+ array_push($this->_onlineUsersData, $row);
+ }
+
+ $result->free();
+ }
+
+ if($channelIDs || $key) {
+ $onlineUsersData = array();
+ foreach($this->_onlineUsersData as $userData) {
+ if($channelIDs && !in_array($userData['channel'], $channelIDs)) {
+ continue;
+ }
+ if($key) {
+ if(!isset($userData[$key])) {
+ return $onlineUsersData;
+ }
+ if($value !== null) {
+ if($userData[$key] == $value) {
+ array_push($onlineUsersData, $userData);
+ } else {
+ continue;
+ }
+ } else {
+ array_push($onlineUsersData, $userData[$key]);
+ }
+ } else {
+ array_push($onlineUsersData, $userData);
+ }
+ }
+ return $onlineUsersData;
+ }
+
+ return $this->_onlineUsersData;
+ }
+
+ function removeUserFromOnlineUsersData($userID=null) {
+ if(!$this->_onlineUsersData) {
+ return;
+ }
+ $userID = ($userID === null) ? $this->getUserID() : $userID;
+ for($i=0; $i<count($this->_onlineUsersData); $i++) {
+ if($this->_onlineUsersData[$i]['userID'] == $userID) {
+ array_splice($this->_onlineUsersData, $i, 1);
+ break;
+ }
+ }
+ }
+
+ function resetOnlineUsersData() {
+ $this->_onlineUsersData = null;
+ }
+
+ function getOnlineUsers($channelIDs=null) {
+ return $this->getOnlineUsersData($channelIDs, 'userName');
+ }
+
+ function getOnlineUserIDs($channelIDs=null) {
+ return $this->getOnlineUsersData($channelIDs, 'userID');
+ }
+
+ function startSession() {
+ if(!session_id()) {
+ // Set the session name:
+ session_name($this->getConfig('sessionName'));
+
+ // Set session cookie parameters:
+ session_set_cookie_params(
+ 0, // The session is destroyed on logout anyway, so no use to set this
+ $this->getConfig('sessionCookiePath'),
+ $this->getConfig('sessionCookieDomain'),
+ $this->getConfig('sessionCookieSecure')
+ );
+
+ // Start the session:
+ session_start();
+
+ // We started a new session:
+ $this->_sessionNew = true;
+ }
+ }
+
+ function destroySession() {
+ if($this->_sessionNew) {
+ // Delete all session variables:
+ $_SESSION = array();
+
+ // Delete the session cookie:
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(
+ session_name(),
+ '',
+ time()-42000,
+ $this->getConfig('sessionCookiePath'),
+ $this->getConfig('sessionCookieDomain'),
+ $this->getConfig('sessionCookieSecure')
+ );
+ }
+
+ // Destroy the session:
+ session_destroy();
+ } else {
+ // Unset all session variables starting with the sessionKeyPrefix:
+ foreach($_SESSION as $key=>$value) {
+ if(strpos($key, $this->getConfig('sessionKeyPrefix')) === 0) {
+ unset($_SESSION[$key]);
+ }
+ }
+ }
+ }
+
+ function regenerateSessionID() {
+ if($this->_sessionNew) {
+ // Regenerate session id:
+ @session_regenerate_id(true);
+ }
+ }
+
+ function getSessionVar($key, $prefix=null) {
+ if($prefix === null)
+ $prefix = $this->getConfig('sessionKeyPrefix');
+
+ // Return the session value if existing:
+ if(isset($_SESSION[$prefix.$key]))
+ return $_SESSION[$prefix.$key];
+ else
+ return null;
+ }
+
+ function setSessionVar($key, $value, $prefix=null) {
+ if($prefix === null)
+ $prefix = $this->getConfig('sessionKeyPrefix');
+
+ // Set the session value:
+ $_SESSION[$prefix.$key] = $value;
+ }
+
+ function getSessionIP() {
+ return $this->getSessionVar('IP');
+ }
+
+ function setSessionIP($ip) {
+ $this->setSessionVar('IP', $ip);
+ }
+
+ function getQueryUserName() {
+ return $this->getSessionVar('QueryUserName');
+ }
+
+ function setQueryUserName($userName) {
+ $this->setSessionVar('QueryUserName', $userName);
+ }
+
+ function getInvitations() {
+ if($this->_invitations === null) {
+ $this->_invitations = array();
+
+ $sql = 'SELECT
+ channel
+ FROM
+ '.$this->getDataBaseTable('invitations').'
+ WHERE
+ userID='.$this->db->makeSafe($this->getUserID()).'
+ AND
+ DATE_SUB(NOW(), interval 1 DAY) < dateTime;';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+
+ while($row = $result->fetch()) {
+ array_push($this->_invitations, $row['channel']);
+ }
+
+ $result->free();
+ }
+ return $this->_invitations;
+ }
+
+ function removeExpiredInvitations() {
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('invitations').'
+ WHERE
+ DATE_SUB(NOW(), interval 1 DAY) > dateTime;';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function addInvitation($userID, $channelID=null) {
+ $this->removeExpiredInvitations();
+
+ $channelID = ($channelID === null) ? $this->getChannel() : $channelID;
+
+ $sql = 'INSERT INTO '.$this->getDataBaseTable('invitations').'(
+ userID,
+ channel,
+ dateTime
+ )
+ VALUES (
+ '.$this->db->makeSafe($userID).',
+ '.$this->db->makeSafe($channelID).',
+ NOW()
+ );';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function removeInvitation($userID, $channelID=null) {
+ $channelID = ($channelID === null) ? $this->getChannel() : $channelID;
+
+ $sql = 'DELETE FROM
+ '.$this->getDataBaseTable('invitations').'
+ WHERE
+ userID='.$this->db->makeSafe($userID).'
+ AND
+ channel='.$this->db->makeSafe($channelID).';';
+
+ // Create a new SQL query:
+ $result = $this->db->sqlQuery($sql);
+
+ // Stop if an error occurs:
+ if($result->error()) {
+ echo $result->getError();
+ die();
+ }
+ }
+
+ function getUserID() {
+ return $this->getSessionVar('UserID');
+ }
+
+ function setUserID($id) {
+ $this->setSessionVar('UserID', $id);
+ }
+
+ function getUserName() {
+ return $this->getSessionVar('UserName');
+ }
+
+ function setUserName($name) {
+ $this->setSessionVar('UserName', $name);
+ }
+
+ function getLoginUserName() {
+ return $this->getSessionVar('LoginUserName');
+ }
+
+ function setLoginUserName($name) {
+ $this->setSessionVar('LoginUserName', $name);
+ }
+
+ function getUserRole() {
+ $userRole = $this->getSessionVar('UserRole');
+ if($userRole === null)
+ return AJAX_CHAT_GUEST;
+ return $userRole;
+ }
+
+ function setUserRole($role) {
+ $this->setSessionVar('UserRole', $role);
+ }
+
+ function getChannel() {
+ return $this->getSessionVar('Channel');
+ }
+
+ function setChannel($channel) {
+ $this->setSessionVar('Channel', $channel);
+
+ // Save the channel enter timestamp:
+ $this->setChannelEnterTimeStamp(time());
+
+ // Update the channel authentication for the socket server:
+ if($this->getConfig('socketServerEnabled')) {
+ $this->updateSocketAuthentication(
+ $this->getUserID(),
+ $this->getSocketRegistrationID(),
+ array($channel,$this->getPrivateMessageID())
+ );
+ }
+
+ // Reset the logs view socket authentication session var:
+ if($this->getSessionVar('logsViewSocketAuthenticated')) {
+ $this->setSessionVar('logsViewSocketAuthenticated', false);
+ }
+ }
+
+ function isLoggedIn() {
+ return (bool)$this->getSessionVar('LoggedIn');
+ }
+
+ function setLoggedIn($bool) {
+ $this->setSessionVar('LoggedIn', $bool);
+ }
+
+ function getLoginTimeStamp() {
+ return $this->getSessionVar('LoginTimeStamp');
+ }
+
+ function setLoginTimeStamp($time) {
+ $this->setSessionVar('LoginTimeStamp', $time);
+ }
+
+ function getChannelEnterTimeStamp() {
+ return $this->getSessionVar('ChannelEnterTimeStamp');
+ }
+
+ function setChannelEnterTimeStamp($time) {
+ $this->setSessionVar('ChannelEnterTimeStamp', $time);
+ }
+
+ function getStatusUpdateTimeStamp() {
+ return $this->getSessionVar('StatusUpdateTimeStamp');
+ }
+
+ function setStatusUpdateTimeStamp($time) {
+ $this->setSessionVar('StatusUpdateTimeStamp', $time);
+ }
+
+ function getInactiveCheckTimeStamp() {
+ return $this->getSessionVar('InactiveCheckTimeStamp');
+ }
+
+ function setInactiveCheckTimeStamp($time) {
+ $this->setSessionVar('InactiveCheckTimeStamp', $time);
+ }
+
+ function getInsertedMessagesRate() {
+ return $this->getSessionVar('InsertedMessagesRate');
+ }
+
+ function setInsertedMessagesRate($rate) {
+ $this->setSessionVar('InsertedMessagesRate', $rate);
+ }
+
+ function getInsertedMessagesRateTimeStamp() {
+ return $this->getSessionVar('InsertedMessagesRateTimeStamp');
+ }
+
+ function setInsertedMessagesRateTimeStamp($time) {
+ $this->setSessionVar('InsertedMessagesRateTimeStamp', $time);
+ }
+
+ function getLangCode() {
+ // Get the langCode from request or cookie:
+ $langCodeCookie = isset($_COOKIE[$this->getConfig('sessionName').'_lang']) ? $_COOKIE[$this->getConfig('sessionName').'_lang'] : null;
+ $langCode = $this->getRequestVar('lang') ? $this->getRequestVar('lang') : $langCodeCookie;
+ // Check if the langCode is valid:
+ if(!in_array($langCode, $this->getConfig('langAvailable'))) {
+ // Determine the user language:
+ $language = new AJAXChatLanguage($this->getConfig('langAvailable'), $this->getConfig('langDefault'));
+ $langCode = $language->getLangCode();
+ }
+ return $langCode;
+ }
+
+ function setLangCodeCookie() {
+ setcookie(
+ $this->getConfig('sessionName').'_lang',
+ $this->getLangCode(),
+ time()+60*60*24*$this->getConfig('sessionCookieLifeTime'),
+ $this->getConfig('sessionCookiePath'),
+ $this->getConfig('sessionCookieDomain'),
+ $this->getConfig('sessionCookieSecure')
+ );
+ }
+
+ function removeUnsafeCharacters($str) {
+ // Remove NO-WS-CTL, non-whitespace control characters (RFC 2822), decimal 1–8, 11–12, 14–31, and 127:
+ return AJAXChatEncoding::removeUnsafeCharacters($str);
+ }
+
+ function subString($str, $start=0, $length=null, $encoding='UTF-8') {
+ return AJAXChatString::subString($str, $start, $length, $encoding);
+ }
+
+ function stringLength($str, $encoding='UTF-8') {
+ return AJAXChatString::stringLength($str, $encoding);
+ }
+
+ function trimMessageText($text) {
+ return $this->trimString($text, 'UTF-8', $this->getConfig('messageTextMaxLength'));
+ }
+
+ function trimUserName($userName) {
+ return $this->trimString($userName, null, $this->getConfig('userNameMaxLength'), true, true);
+ }
+
+ function trimChannelName($channelName) {
+ return $this->trimString($channelName, null, null, true, true);
+ }
+
+ function trimString($str, $sourceEncoding=null, $maxLength=null, $replaceWhitespace=false, $decodeEntities=false, $htmlEntitiesMap=null) {
+ // Make sure the string contains valid unicode:
+ $str = $this->convertToUnicode($str, $sourceEncoding);
+
+ // Make sure the string contains no unsafe characters:
+ $str = $this->removeUnsafeCharacters($str);
+
+ // Strip whitespace from the beginning and end of the string:
+ $str = trim($str);
+
+ if($replaceWhitespace) {
+ // Replace any whitespace in the userName with the underscore "_":
+ $str = preg_replace('/\s/u', '_', $str);
+ }
+
+ if($decodeEntities) {
+ // Decode entities:
+ $str = $this->decodeEntities($str, 'UTF-8', $htmlEntitiesMap);
+ }
+
+ if($maxLength) {
+ // Cut the string to the allowed length:
+ $str = $this->subString($str, 0, $maxLength);
+ }
+
+ return $str;
+ }
+
+ function convertToUnicode($str, $sourceEncoding=null) {
+ if($sourceEncoding === null) {
+ $sourceEncoding = $this->getConfig('sourceEncoding');
+ }
+ return $this->convertEncoding($str, $sourceEncoding, 'UTF-8');
+ }
+
+ function convertFromUnicode($str, $contentEncoding=null) {
+ if($contentEncoding === null) {
+ $contentEncoding = $this->getConfig('contentEncoding');
+ }
+ return $this->convertEncoding($str, 'UTF-8', $contentEncoding);
+ }
+
+ function convertEncoding($str, $charsetFrom, $charsetTo) {
+ return AJAXChatEncoding::convertEncoding($str, $charsetFrom, $charsetTo);
+ }
+
+ function encodeEntities($str, $encoding='UTF-8', $convmap=null) {
+ return AJAXChatEncoding::encodeEntities($str, $encoding, $convmap);
+ }
+
+ function decodeEntities($str, $encoding='UTF-8', $htmlEntitiesMap=null) {
+ return AJAXChatEncoding::decodeEntities($str, $encoding, $htmlEntitiesMap);
+ }
+
+ function htmlEncode($str) {
+ return AJAXChatEncoding::htmlEncode($str, $this->getConfig('contentEncoding'));
+ }
+
+ function encodeSpecialChars($str) {
+ return AJAXChatEncoding::encodeSpecialChars($str);
+ }
+
+ function decodeSpecialChars($str) {
+ return AJAXChatEncoding::decodeSpecialChars($str);
+ }
+
+ function ipToStorageFormat($ip) {
+ if(function_exists('inet_pton')) {
+ // ipv4 & ipv6:
+ return @inet_pton($ip);
+ }
+ // Only ipv4:
+ return @pack('N',@ip2long($ip));
+ }
+
+ function ipFromStorageFormat($ip) {
+ if(function_exists('inet_ntop')) {
+ // ipv4 & ipv6:
+ return @inet_ntop($ip);
+ }
+ // Only ipv4:
+ $unpacked = @unpack('Nlong',$ip);
+ if(isset($unpacked['long'])) {
+ return @long2ip($unpacked['long']);
+ }
+ return null;
+ }
+
+ function getConfig($key, $subkey=null) {
+ if($subkey)
+ return $this->_config[$key][$subkey];
+ else
+ return $this->_config[$key];
+ }
+
+ function setConfig($key, $subkey, $value) {
+ if($subkey) {
+ if(!isset($this->_config[$key])) {
+ $this->_config[$key] = array();
+ }
+ $this->_config[$key][$subkey] = $value;
+ } else {
+ $this->_config[$key] = $value;
+ }
+ }
+
+ function getLang($key=null) {
+ if(!$this->_lang) {
+ // Include the language file:
+ $lang = null;
+ require(AJAX_CHAT_PATH.'lib/lang/'.$this->getLangCode().'.php');
+ $this->_lang = &$lang;
+ }
+ if($key === null)
+ return $this->_lang;
+ if(isset($this->_lang[$key]))
+ return $this->_lang[$key];
+ return null;
+ }
+
+ function getChatURL() {
+ if(defined('AJAX_CHAT_URL')) {
+ return AJAX_CHAT_URL;
+ }
+
+ return
+ (isset($_SERVER['HTTPS']) ? 'https://' : 'http://').
+ (isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : '').
+ (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'].
+ (isset($_SERVER['HTTPS']) && $_SERVER['SERVER_PORT'] == 443 || $_SERVER['SERVER_PORT'] == 80 ? '' : ':'.$_SERVER['SERVER_PORT']))).
+ substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')+1);
+ }
+
+ function getIDFromName($userName) {
+ $userDataArray = $this->getOnlineUsersData(null,'userName',$userName);
+ if($userDataArray && isset($userDataArray[0])) {
+ return $userDataArray[0]['userID'];
+ }
+ return null;
+ }
+
+ function getNameFromID($userID) {
+ $userDataArray = $this->getOnlineUsersData(null,'userID',$userID);
+ if($userDataArray && isset($userDataArray[0])) {
+ return $userDataArray[0]['userName'];
+ }
+ return null;
+ }
+
+ function getChannelFromID($userID) {
+ $userDataArray = $this->getOnlineUsersData(null,'userID',$userID);
+ if($userDataArray && isset($userDataArray[0])) {
+ return $userDataArray[0]['channel'];
+ }
+ return null;
+ }
+
+ function getIPFromID($userID) {
+ $userDataArray = $this->getOnlineUsersData(null,'userID',$userID);
+ if($userDataArray && isset($userDataArray[0])) {
+ return $userDataArray[0]['ip'];
+ }
+ return null;
+ }
+
+ function getRoleFromID($userID) {
+ $userDataArray = $this->getOnlineUsersData(null,'userID',$userID);
+ if($userDataArray && isset($userDataArray[0])) {
+ return $userDataArray[0]['userRole'];
+ }
+ return null;
+ }
+
+ function getChannelNames() {
+ return array_flip($this->getChannels());
+ }
+
+ function getChannelIDFromChannelName($channelName) {
+ if(!$channelName)
+ return null;
+ $channels = $this->getAllChannels();
+ if(array_key_exists($channelName,$channels)) {
+ return $channels[$channelName];
+ }
+ $channelID = null;
+ // Check if the requested channel is the own private channel:
+ if($channelName == $this->getPrivateChannelName()) {
+ return $this->getPrivateChannelID();
+ }
+ // Try to retrieve a private room ID:
+ $strlenChannelName = $this->stringLength($channelName);
+ $strlenPrefix = $this->stringLength($this->getConfig('privateChannelPrefix'));
+ $strlenSuffix = $this->stringLength($this->getConfig('privateChannelSuffix'));
+ if($this->subString($channelName,0,$strlenPrefix) == $this->getConfig('privateChannelPrefix')
+ && $this->subString($channelName,$strlenChannelName-$strlenSuffix) == $this->getConfig('privateChannelSuffix')) {
+ $userName = $this->subString(
+ $channelName,
+ $strlenPrefix,
+ $strlenChannelName-($strlenPrefix+$strlenSuffix)
+ );
+ $userID = $this->getIDFromName($userName);
+ if($userID !== null) {
+ $channelID = $this->getPrivateChannelID($userID);
+ }
+ }
+ return $channelID;
+ }
+
+ function getChannelNameFromChannelID($channelID) {
+ foreach($this->getAllChannels() as $key=>$value) {
+ if($value == $channelID) {
+ return $key;
+ }
+ }
+ // Try to retrieve a private room name:
+ if($channelID == $this->getPrivateChannelID()) {
+ return $this->getPrivateChannelName();
+ }
+ $userName = $this->getNameFromID($channelID-$this->getConfig('privateChannelDiff'));
+ if($userName === null) {
+ return null;
+ }
+ return $this->getPrivateChannelName($userName);
+ }
+
+ function getChannelName() {
+ return $this->getChannelNameFromChannelID($this->getChannel());
+ }
+
+ function getPrivateChannelName($userName=null) {
+ if($userName === null) {
+ $userName = $this->getUserName();
+ }
+ return $this->getConfig('privateChannelPrefix').$userName.$this->getConfig('privateChannelSuffix');
+ }
+
+ function getPrivateChannelID($userID=null) {
+ if($userID === null) {
+ $userID = $this->getUserID();
+ }
+ return $userID + $this->getConfig('privateChannelDiff');
+ }
+
+ function getPrivateMessageID($userID=null) {
+ if($userID === null) {
+ $userID = $this->getUserID();
+ }
+ return $userID + $this->getConfig('privateMessageDiff');
+ }
+
+ function isAllowedToSendPrivateMessage() {
+ if($this->getConfig('allowPrivateMessages') || $this->getUserRole() == AJAX_CHAT_ADMIN) {
+ return true;
+ }
+ return false;
+ }
+
+ function isAllowedToCreatePrivateChannel() {
+ if($this->getConfig('allowPrivateChannels')) {
+ switch($this->getUserRole()) {
+ case AJAX_CHAT_USER:
+ return true;
+ case AJAX_CHAT_MODERATOR:
+ return true;
+ case AJAX_CHAT_ADMIN:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
+ function isAllowedToListHiddenUsers() {
+ // Hidden users are users within private or restricted channels:
+ switch($this->getUserRole()) {
+ case AJAX_CHAT_MODERATOR:
+ return true;
+ case AJAX_CHAT_ADMIN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ function isUserOnline($userID=null) {
+ $userID = ($userID === null) ? $this->getUserID() : $userID;
+ $userDataArray = $this->getOnlineUsersData(null,'userID',$userID);
+ if($userDataArray && count($userDataArray) > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isUserNameInUse($userName=null) {
+ $userName = ($userName === null) ? $this->getUserName() : $userName;
+ $userDataArray = $this->getOnlineUsersData(null,'userName',$userName);
+ if($userDataArray && count($userDataArray) > 0) {
+ return true;
+ }
+ return false;
+ }
+
+ function isUserBanned($userName, $userID=null, $ip=null) {
+ if($userID !== null) {
+ $bannedUserDataArray = $this->getBannedUsersData('userID',$userID);
+ if($bannedUserDataArray && isset($bannedUserDataArray[0])) {
+ return true;
+ }
+ }
+ if($ip !== null) {
+ $bannedUserDataArray = $this->getBannedUsersData('ip',$ip);
+ if($bannedUserDataArray && isset($bannedUserDataArray[0])) {
+ return true;
+ }
+ }
+ $bannedUserDataArray = $this->getBannedUsersData('userName',$userName);
+ if($bannedUserDataArray && isset($bannedUserDataArray[0])) {
+ return true;
+ }
+ return false;
+ }
+
+ function isMaxUsersLoggedIn() {
+ if(count($this->getOnlineUsersData()) >= $this->getConfig('maxUsersLoggedIn')) {
+ return true;
+ }
+ return false;
+ }
+
+ function validateChannel($channelID) {
+ if($channelID === null) {
+ return false;
+ }
+ // Return true for normal channels the user has acces to:
+ if(in_array($channelID, $this->getChannels())) {
+ return true;
+ }
+ // Return true if the user is allowed to join his own private channel:
+ if($channelID == $this->getPrivateChannelID() && $this->isAllowedToCreatePrivateChannel()) {
+ return true;
+ }
+ // Return true if the user has been invited to a restricted or private channel:
+ if(in_array($channelID, $this->getInvitations())) {
+ return true;
+ }
+ // No valid channel, return false:
+ return false;
+ }
+
+ function createGuestUserName() {
+ $maxLength = $this->getConfig('userNameMaxLength')
+ - $this->stringLength($this->getConfig('guestUserPrefix'))
+ - $this->stringLength($this->getConfig('guestUserSuffix'));
+
+ // seed with microseconds since last "whole" second:
+ mt_srand((double)microtime()*1000000);
+
+ // Create a random userName using numbers between 100000 and 999999:
+ $userName = substr(mt_rand(100000, 999999), 0, $maxLength);
+
+ return $this->getConfig('guestUserPrefix').$userName.$this->getConfig('guestUserSuffix');
+ }
+
+ // Guest userIDs must not interfere with existing userIDs and must be lower than privateChannelDiff:
+ function createGuestUserID() {
+ // seed with microseconds since last "whole" second:
+ mt_srand((double)microtime()*1000000);
+
+ return mt_rand($this->getConfig('minGuestUserID'), $this->getConfig('privateChannelDiff')-1);
+ }
+
+ function getGuestUser() {
+ if(!$this->getConfig('allowGuestLogins'))
+ return null;
+
+ if($this->getConfig('allowGuestUserName')) {
+ $maxLength = $this->getConfig('userNameMaxLength')
+ - $this->stringLength($this->getConfig('guestUserPrefix'))
+ - $this->stringLength($this->getConfig('guestUserSuffix'));
+
+ // Trim guest userName:
+ $userName = $this->trimString($this->getRequestVar('userName'), null, $maxLength, true, true);
+
+ // If given userName is invalid, create one:
+ if(!$userName) {
+ $userName = $this->createGuestUserName();
+ } else {
+ // Add the guest users prefix and suffix to the given userName:
+ $userName = $this->getConfig('guestUserPrefix').$userName.$this->getConfig('guestUserSuffix');
+ }
+ } else {
+ $userName = $this->createGuestUserName();
+ }
+
+ $userData = array();
+ $userData['userID'] = $this->createGuestUserID();
+ $userData['userName'] = $userName;
+ $userData['userRole'] = AJAX_CHAT_GUEST;
+ return $userData;
+ }
+
+ function getCustomVar($key) {
+ if(!isset($this->_customVars))
+ $this->_customVars = array();
+ if(!isset($this->_customVars[$key]))
+ return null;
+ return $this->_customVars[$key];
+ }
+
+ function setCustomVar($key, $value) {
+ if(!isset($this->_customVars))
+ $this->_customVars = array();
+ $this->_customVars[$key] = $value;
+ }
+
+ // Override to replace custom template tags:
+ // Return the replacement for the given tag (and given tagContent)
+ function replaceCustomTemplateTags($tag, $tagContent) {
+ return null;
+ }
+
+ // Override to initialize custom configuration settings:
+ function initCustomConfig() {
+ }
+
+ // Override to add custom request variables:
+ // Add values to the request variables array: $this->_requestVars['customVariable'] = null;
+ function initCustomRequestVars() {
+ }
+
+ // Override to add custom session code right after the session has been started:
+ function initCustomSession() {
+ }
+
+ // Override, to parse custom info requests:
+ // $infoRequest contains the current info request
+ // Add info responses using the method addInfoMessage($info, $type)
+ function parseCustomInfoRequest($infoRequest) {
+ }
+
+ // Override to replace custom text:
+ // Return replaced text
+ // $text contains the whole message
+ function replaceCustomText(&$text) {
+ return $text;
+ }
+
+ // Override to add custom commands:
+ // Return true if a custom command has been successfully parsed, else false
+ // $text contains the whole message, $textParts the message split up as words array
+ function parseCustomCommands($text, $textParts) {
+ return false;
+ }
+
+ // Override to perform custom actions on new messages:
+ // Return true if message may be inserted, else false
+ // $text contains the whole message
+ function onNewMessage($text) {
+ return true;
+ }
+
+ // Override to perform custom actions on new messages:
+ // Method to set the style cookie depending on user data
+ function setStyle() {
+ }
+
+ // Override:
+ // Returns true if the userID of the logged in user is identical to the userID of the authentication system
+ // or the user is authenticated as guest in the chat and the authentication system
+ function revalidateUserID() {
+ return true;
+ }
+
+ // Override:
+ // Returns an associative array containing userName, userID and userRole
+ // Returns null if login is invalid
+ function getValidLoginUserData() {
+ // Check if we have a valid registered user:
+ if(false) {
+ // Here is the place to check user authentication
+ } else {
+ // Guest users:
+ return $this->getGuestUser();
+ }
+ }
+
+ // Override:
+ // Store the channels the current user has access to
+ // Make sure channel names don't contain any whitespace
+ function &getChannels() {
+ if($this->_channels === null) {
+ $this->_channels = $this->getAllChannels();
+ }
+ return $this->_channels;
+ }
+
+ // Override:
+ // Store all existing channels
+ // Make sure channel names don't contain any whitespace
+ function &getAllChannels() {
+ if($this->_allChannels === null) {
+ $this->_allChannels = array();
+
+ // Default channel, public to everyone:
+ $this->_allChannels[$this->trimChannelName($this->getConfig('defaultChannelName'))] = $this->getConfig('defaultChannelID');
+ }
+ return $this->_allChannels;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatDataBase.php b/library/ajaxchat/chat/lib/class/AJAXChatDataBase.php
new file mode 100644
index 000000000..2143c5aa0
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatDataBase.php
@@ -0,0 +1,81 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to initialize the DataBase connection:
+class AJAXChatDataBase {
+
+ var $_db;
+
+ function __construct(&$dbConnectionConfig) {
+ switch($dbConnectionConfig['type']) {
+ case 'mysqli':
+ $this->_db = new AJAXChatDatabaseMySQLi($dbConnectionConfig);
+ break;
+ case 'mysql':
+ $this->_db = new AJAXChatDatabaseMySQL($dbConnectionConfig);
+ break;
+ default:
+ // Use MySQLi if available, else MySQL (and check the type of a given database connection object):
+ if(function_exists('mysqli_connect') && (!$dbConnectionConfig['link'] || is_object($dbConnectionConfig['link']))) {
+ $this->_db = new AJAXChatDatabaseMySQLi($dbConnectionConfig);
+ } else {
+ $this->_db = new AJAXChatDatabaseMySQL($dbConnectionConfig);
+ }
+ }
+ }
+
+ // Method to connect to the DataBase server:
+ function connect(&$dbConnectionConfig) {
+ return $this->_db->connect($dbConnectionConfig);
+ }
+
+ // Method to select the DataBase:
+ function select($dbName) {
+ return $this->_db->select($dbName);
+ }
+
+ // Method to determine if an error has occured:
+ function error() {
+ return $this->_db->error();
+ }
+
+ // Method to return the error report:
+ function getError() {
+ return $this->_db->getError();
+ }
+
+ // Method to return the connection identifier:
+ function &getConnectionID() {
+ return $this->_db->getConnectionID();
+ }
+
+ // Method to prevent SQL injections:
+ function makeSafe($value) {
+ return $this->_db->makeSafe($value);
+ }
+
+ // Method to perform SQL queries:
+ function sqlQuery($sql) {
+ return $this->_db->sqlQuery($sql);
+ }
+
+ // Method to retrieve the current DataBase name:
+ function getName() {
+ return $this->_db->getName();
+ //If your database has hyphens ( - ) in it, try using this instead:
+ //return '`'.$this->_db->getName().'`';
+ }
+
+ // Method to retrieve the last inserted ID:
+ function getLastInsertedID() {
+ return $this->_db->getLastInsertedID();
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatEncoding.php b/library/ajaxchat/chat/lib/class/AJAXChatEncoding.php
new file mode 100644
index 000000000..96b2482c7
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatEncoding.php
@@ -0,0 +1,138 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to provide static encoding methods
+class AJAXChatEncoding {
+
+ // Helper function to store special chars as we cannot use static class members in PHP4:
+ public static function getSpecialChars() {
+ static $specialChars;
+ if(!$specialChars) {
+ // As &apos; is not supported by IE, we use &#39; as replacement for "'":
+ $specialChars = array('&'=>'&amp;', '<'=>'&lt;', '>'=>'&gt;', "'"=>'&#39;', '"'=>'&quot;');
+ }
+ return $specialChars;
+ }
+
+ // Helper function to store Regular expression for NO-WS-CTL as we cannot use static class members in PHP4:
+ public static function getRegExp_NO_WS_CTL() {
+ static $regExp_NO_WS_CTL;
+ if(!$regExp_NO_WS_CTL) {
+ // Regular expression for NO-WS-CTL, non-whitespace control characters (RFC 2822), decimal 1–8, 11–12, 14–31, and 127:
+ $regExp_NO_WS_CTL = '/[\x0\x1\x2\x3\x4\x5\x6\x7\x8\xB\xC\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F]/';
+ }
+ return $regExp_NO_WS_CTL;
+ }
+
+ public static function convertEncoding($str, $charsetFrom, $charsetTo) {
+ if(function_exists('mb_convert_encoding')) {
+ return mb_convert_encoding($str, $charsetTo, $charsetFrom);
+ }
+ if(function_exists('iconv')) {
+ return iconv($charsetFrom, $charsetTo, $str);
+ }
+ if(($charsetFrom == 'UTF-8') && ($charsetTo == 'ISO-8859-1')) {
+ return utf8_decode($str);
+ }
+ if(($charsetFrom == 'ISO-8859-1') && ($charsetTo == 'UTF-8')) {
+ return utf8_encode($str);
+ }
+ return $str;
+ }
+
+ public static function htmlEncode($str, $contentCharset='UTF-8') {
+ switch($contentCharset) {
+ case 'UTF-8':
+ // Encode only special chars (&, <, >, ', ") as entities:
+ return AJAXChatEncoding::encodeSpecialChars($str);
+ break;
+ case 'ISO-8859-1':
+ case 'ISO-8859-15':
+ // Encode special chars and all extended characters above ISO-8859-1 charset as entities, then convert to content charset:
+ return AJAXChatEncoding::convertEncoding(AJAXChatEncoding::encodeEntities($str, 'UTF-8', array(
+ 0x26, 0x26, 0, 0xFFFF, // &
+ 0x3C, 0x3C, 0, 0xFFFF, // <
+ 0x3E, 0x3E, 0, 0xFFFF, // >
+ 0x27, 0x27, 0, 0xFFFF, // '
+ 0x22, 0x22, 0, 0xFFFF, // "
+ 0x100, 0x2FFFF, 0, 0xFFFF // above ISO-8859-1
+ )), 'UTF-8', $contentCharset);
+ break;
+ default:
+ // Encode special chars and all characters above ASCII charset as entities, then convert to content charset:
+ return AJAXChatEncoding::convertEncoding(AJAXChatEncoding::encodeEntities($str, 'UTF-8', array(
+ 0x26, 0x26, 0, 0xFFFF, // &
+ 0x3C, 0x3C, 0, 0xFFFF, // <
+ 0x3E, 0x3E, 0, 0xFFFF, // >
+ 0x27, 0x27, 0, 0xFFFF, // '
+ 0x22, 0x22, 0, 0xFFFF, // "
+ 0x80, 0x2FFFF, 0, 0xFFFF // above ASCII
+ )), 'UTF-8', $contentCharset);
+ }
+ }
+
+ public static function encodeSpecialChars($str) {
+ return strtr($str, AJAXChatEncoding::getSpecialChars());
+ }
+
+ public static function decodeSpecialChars($str) {
+ return strtr($str, array_flip(AJAXChatEncoding::getSpecialChars()));
+ }
+
+ public static function encodeEntities($str, $encoding='UTF-8', $convmap=null) {
+ if($convmap && function_exists('mb_encode_numericentity')) {
+ return mb_encode_numericentity($str, $convmap, $encoding);
+ }
+ return htmlentities($str, ENT_QUOTES, $encoding);
+ }
+
+ public static function decodeEntities($str, $encoding='UTF-8', $htmlEntitiesMap=null) {
+ // Due to PHP bug #25670, html_entity_decode does not work with UTF-8 for PHP versions < 5:
+ if(function_exists('html_entity_decode') && version_compare(phpversion(), 5, '>=')) {
+ // Replace numeric and literal entities:
+ $str = html_entity_decode($str, ENT_QUOTES, $encoding);
+ // Replace additional literal HTML entities if an HTML entities map is given:
+ if($htmlEntitiesMap) {
+ $str = strtr($str, $htmlEntitiesMap);
+ }
+ } else {
+ // Replace numeric entities:
+ $str = preg_replace('~&#([0-9]+);~e', 'AJAXChatEncoding::unicodeChar("\\1")', $str);
+ $str = preg_replace('~&#x([0-9a-f]+);~ei', 'AJAXChatEncoding::unicodeChar(hexdec("\\1"))', $str);
+ // Replace literal entities:
+ $htmlEntitiesMap = $htmlEntitiesMap ? $htmlEntitiesMap : array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES));
+ $str = strtr($str, $htmlEntitiesMap);
+ }
+ return $str;
+ }
+
+ public static function unicodeChar($c) {
+ if($c <= 0x7F) {
+ return chr($c);
+ } else if($c <= 0x7FF) {
+ return chr(0xC0 | $c >> 6) . chr(0x80 | $c & 0x3F);
+ } else if($c <= 0xFFFF) {
+ return chr(0xE0 | $c >> 12) . chr(0x80 | $c >> 6 & 0x3F)
+ . chr(0x80 | $c & 0x3F);
+ } else if($c <= 0x10FFFF) {
+ return chr(0xF0 | $c >> 18) . chr(0x80 | $c >> 12 & 0x3F)
+ . chr(0x80 | $c >> 6 & 0x3F)
+ . chr(0x80 | $c & 0x3F);
+ } else {
+ return null;
+ }
+ }
+
+ public static function removeUnsafeCharacters($str) {
+ // Remove NO-WS-CTL, non-whitespace control characters (RFC 2822), decimal 1–8, 11–12, 14–31, and 127:
+ return preg_replace(AJAXChatEncoding::getRegExp_NO_WS_CTL(), '', $str);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatFileSystem.php b/library/ajaxchat/chat/lib/class/AJAXChatFileSystem.php
new file mode 100644
index 000000000..c9626c36a
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatFileSystem.php
@@ -0,0 +1,22 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to provide methods for file system access:
+class AJAXChatFileSystem {
+
+ public static function getFileContents($file) {
+ if(function_exists('file_get_contents')) {
+ return file_get_contents($file);
+ } else {
+ return(implode('', file($file)));
+ }
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatHTTPHeader.php b/library/ajaxchat/chat/lib/class/AJAXChatHTTPHeader.php
new file mode 100644
index 000000000..7340bfcf0
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatHTTPHeader.php
@@ -0,0 +1,56 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to manage HTTP header
+class AJAXChatHTTPHeader {
+
+ var $_contentType;
+ var $_constant;
+ var $_noCache;
+
+ function __construct($encoding='UTF-8', $contentType=null, $noCache=true) {
+ if($contentType) {
+ $this->_contentType = $contentType.'; charset='.$encoding;
+ $this->_constant = true;
+ } else {
+ if(isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'],'application/xhtml+xml') !== false)) {
+ $this->_contentType = 'application/xhtml+xml; charset='.$encoding;
+ } else {
+ $this->_contentType = 'text/html; charset='.$encoding;
+ }
+ $this->_constant = false;
+ }
+ $this->_noCache = $noCache;
+ }
+
+ // Method to send the HTTP header:
+ function send() {
+ // Prevent caching:
+ if($this->_noCache) {
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+ }
+
+ // Send the content-type-header:
+ header('Content-Type: '.$this->_contentType);
+
+ // Send vary header if content-type varies (important for proxy-caches):
+ if(!$this->_constant) {
+ header('Vary: Accept');
+ }
+ }
+
+ // Method to return the content-type string:
+ function getContentType() {
+ // Return the content-type string:
+ return $this->_contentType;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatLanguage.php b/library/ajaxchat/chat/lib/class/AJAXChatLanguage.php
new file mode 100644
index 000000000..b19724710
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatLanguage.php
@@ -0,0 +1,102 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+class AJAXChatLanguage {
+
+ var $_regExpAcceptLangCode;
+ var $_availableLangCodes;
+ var $_defaultLangCode;
+ var $_strictMode;
+ var $_langCode;
+
+ function __construct($availableLangCodes, $defaultLangCode, $langCode=null, $strictMode=false) {
+ $this->_regExpAcceptLangCode = '/^([a-z]{1,8}(?:-[a-z]{1,8})*)(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i';
+ $this->_availableLangCodes = $availableLangCodes;
+ $this->_defaultLangCode = $defaultLangCode;
+ if($langCode && in_array($langCode, $availableLangCodes)) {
+ $this->_langCode = $langCode;
+ }
+ $this->_strictMode = $strictMode;
+ }
+
+ // Method to detect the language code from the HTTP_ACCEPT_LANGUAGE header:
+ function detectLangCode() {
+ // If HTTP_ACCEPT_LANGUAGE is empty use defaultLangCode:
+ if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+ $this->_langCode = $this->_defaultLangCode;
+ return;
+ }
+
+ // Split up the HTTP_ACCEPT_LANGUAGE header:
+ $acceptedLanguages = preg_split('/,\s*/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+
+ $currentLangCode = $this->_defaultLangCode;
+ $currentLangQuality = 0.0;
+
+ foreach($acceptedLanguages as $acceptedLanguage) {
+ // Parse the language string:
+ $match = preg_match($this->_regExpAcceptLangCode, $acceptedLanguage, $matches);
+ // Check if the syntax is valid:
+ if(!$match) {
+ continue;
+ }
+
+ // Get and split the language code:
+ $langCodeParts = explode ('-', $matches[1]);
+
+ // Get the language quality given as float value:
+ if(isset($matches[2])) {
+ $langQuality = (float)$matches[2];
+ } else {
+ // Missing language quality value is maximum quality:
+ $langQuality = 1.0;
+ }
+
+ // Go through it until the language code is empty:
+ while(count($langCodeParts)) {
+ // Join the current langCodeParts:
+ $langCode = strtolower(join('-', $langCodeParts));
+ // Check if the langCode is in the available list:
+ if(in_array($langCode, $this->_availableLangCodes)) {
+ // Check the quality setting:
+ if ($langQuality > $currentLangQuality) {
+ $currentLangCode = $langCode;
+ $currentLangQuality = $langQuality;
+ break;
+ }
+ }
+ // If strict mode is set, don't minimalize the language code:
+ if($this->_strictMode) {
+ break;
+ }
+ // else chop off the right part:
+ array_pop($langCodeParts);
+ }
+ }
+
+ $this->_langCode = $currentLangCode;
+ }
+
+ function getLangCode() {
+ if(!$this->_langCode) {
+ $this->detectLangCode();
+ }
+ return $this->_langCode;
+ }
+
+ function setLangCode($langCode) {
+ $this->_langCode = $langCode;
+ }
+
+ function getLangCodes() {
+ return $this->_availableLangCodes;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatMySQLDataBase.php b/library/ajaxchat/chat/lib/class/AJAXChatMySQLDataBase.php
new file mode 100644
index 000000000..6dca348d1
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatMySQLDataBase.php
@@ -0,0 +1,92 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to initialize the MySQL DataBase connection:
+class AJAXChatDataBaseMySQL {
+
+ var $_connectionID;
+ var $_errno = 0;
+ var $_error = '';
+ var $_dbName;
+
+ function __construct(&$dbConnectionConfig) {
+ $this->_connectionID = $dbConnectionConfig['link'];
+ $this->_dbName = $dbConnectionConfig['name'];
+ }
+
+ // Method to connect to the DataBase server:
+ function connect(&$dbConnectionConfig) {
+ $this->_connectionID = @mysql_connect(
+ $dbConnectionConfig['host'],
+ $dbConnectionConfig['user'],
+ $dbConnectionConfig['pass'],
+ true
+ );
+ if(!$this->_connectionID) {
+ $this->_errno = null;
+ $this->_error = 'Database connection failed.';
+ return false;
+ }
+ return true;
+ }
+
+ // Method to select the DataBase:
+ function select($dbName) {
+ if(!@mysql_select_db($dbName, $this->_connectionID)) {
+ $this->_errno = mysql_errno($this->_connectionID);
+ $this->_error = mysql_error($this->_connectionID);
+ return false;
+ }
+ $this->_dbName = $dbName;
+ return true;
+ }
+
+ // Method to determine if an error has occured:
+ function error() {
+ return (bool)$this->_error;
+ }
+
+ // Method to return the error report:
+ function getError() {
+ if($this->error()) {
+ $str = 'Error-Report: ' .$this->_error."\n";
+ $str .= 'Error-Code: '.$this->_errno."\n";
+ } else {
+ $str = 'No errors.'."\n";
+ }
+ return $str;
+ }
+
+ // Method to return the connection identifier:
+ function &getConnectionID() {
+ return $this->_connectionID;
+ }
+
+ // Method to prevent SQL injections:
+ function makeSafe($value) {
+ return "'".mysql_real_escape_string($value, $this->_connectionID)."'";
+ }
+
+ // Method to perform SQL queries:
+ function sqlQuery($sql) {
+ return new AJAXChatMySQLQuery($sql, $this->_connectionID);
+ }
+
+ // Method to retrieve the current DataBase name:
+ function getName() {
+ return $this->_dbName;
+ }
+
+ // Method to retrieve the last inserted ID:
+ function getLastInsertedID() {
+ return mysql_insert_id($this->_connectionID);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatMySQLQuery.php b/library/ajaxchat/chat/lib/class/AJAXChatMySQLQuery.php
new file mode 100644
index 000000000..f2f3fd466
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatMySQLQuery.php
@@ -0,0 +1,89 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to perform SQL (MySQL) queries:
+class AJAXChatMySQLQuery {
+
+ var $_connectionID;
+ var $_sql = '';
+ var $_result = 0;
+ var $_errno = 0;
+ var $_error = '';
+
+ // Constructor:
+ function __construct($sql, $connectionID = null) {
+ $this->_sql = trim($sql);
+ $this->_connectionID = $connectionID;
+ if($this->_connectionID) {
+ $this->_result = mysql_query($this->_sql, $this->_connectionID);
+ if(!$this->_result) {
+ $this->_errno = mysql_errno($this->_connectionID);
+ $this->_error = mysql_error($this->_connectionID);
+ }
+ } else {
+ $this->_result = mysql_query($this->_sql);
+ if(!$this->_result) {
+ $this->_errno = mysql_errno();
+ $this->_error = mysql_error();
+ }
+ }
+ }
+
+ // Returns true if an error occured:
+ function error() {
+ // Returns true if the Result-ID is valid:
+ return !(bool)($this->_result);
+ }
+
+ // Returns an Error-String:
+ function getError() {
+ if($this->error()) {
+ $str = 'Query: ' .$this->_sql ."\n";
+ $str .= 'Error-Report: ' .$this->_error."\n";
+ $str .= 'Error-Code: '.$this->_errno;
+ } else {
+ $str = "No errors.";
+ }
+ return $str;
+ }
+
+ // Returns the content:
+ function fetch() {
+ if($this->error()) {
+ return null;
+ } else {
+ return mysql_fetch_assoc($this->_result);
+ }
+ }
+
+ // Returns the number of rows (SELECT or SHOW):
+ function numRows() {
+ if($this->error()) {
+ return null;
+ } else {
+ return mysql_num_rows($this->_result);
+ }
+ }
+
+ // Returns the number of affected rows (INSERT, UPDATE, REPLACE or DELETE):
+ function affectedRows() {
+ if($this->error()) {
+ return null;
+ } else {
+ return mysql_affected_rows($this->_connectionID);
+ }
+ }
+
+ // Frees the memory:
+ function free() {
+ @mysql_free_result($this->_result);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatMySQLiDataBase.php b/library/ajaxchat/chat/lib/class/AJAXChatMySQLiDataBase.php
new file mode 100644
index 000000000..9bc611e2d
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatMySQLiDataBase.php
@@ -0,0 +1,91 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to initialize the MySQL DataBase connection:
+class AJAXChatDataBaseMySQLi {
+
+ var $_connectionID;
+ var $_errno = 0;
+ var $_error = '';
+ var $_dbName;
+
+ function __construct(&$dbConnectionConfig) {
+ $this->_connectionID = $dbConnectionConfig['link'];
+ $this->_dbName = $dbConnectionConfig['name'];
+ }
+
+ // Method to connect to the DataBase server:
+ function connect(&$dbConnectionConfig) {
+ @$this->_connectionID = new mysqli(
+ $dbConnectionConfig['host'],
+ $dbConnectionConfig['user'],
+ $dbConnectionConfig['pass']
+ );
+ if($this->_connectionID->connect_errno) {
+ $this->_errno = mysqli_connect_errno();
+ $this->_error = mysqli_connect_error();
+ return false;
+ }
+ return true;
+ }
+
+ // Method to select the DataBase:
+ function select($dbName) {
+ if(!$this->_connectionID->select_db($dbName)) {
+ $this->_errno = $this->_connectionID->errno;
+ $this->_error = $this->_connectionID->error;
+ return false;
+ }
+ $this->_dbName = $dbName;
+ return true;
+ }
+
+ // Method to determine if an error has occured:
+ function error() {
+ return (bool)$this->_error;
+ }
+
+ // Method to return the error report:
+ function getError() {
+ if($this->error()) {
+ $str = 'Error-Report: ' .$this->_error."\n";
+ $str .= 'Error-Code: '.$this->_errno."\n";
+ } else {
+ $str = 'No errors.'."\n";
+ }
+ return $str;
+ }
+
+ // Method to return the connection identifier:
+ function &getConnectionID() {
+ return $this->_connectionID;
+ }
+
+ // Method to prevent SQL injections:
+ function makeSafe($value) {
+ return "'".$this->_connectionID->escape_string($value)."'";
+ }
+
+ // Method to perform SQL queries:
+ function sqlQuery($sql) {
+ return new AJAXChatMySQLiQuery($sql, $this->_connectionID);
+ }
+
+ // Method to retrieve the current DataBase name:
+ function getName() {
+ return $this->_dbName;
+ }
+
+ // Method to retrieve the last inserted ID:
+ function getLastInsertedID() {
+ return $this->_connectionID->insert_id;
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatMySQLiQuery.php b/library/ajaxchat/chat/lib/class/AJAXChatMySQLiQuery.php
new file mode 100644
index 000000000..f81afd886
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatMySQLiQuery.php
@@ -0,0 +1,81 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to perform SQL (MySQLi) queries:
+class AJAXChatMySQLiQuery {
+
+ var $_connectionID;
+ var $_sql = '';
+ var $_result = 0;
+ var $_errno = 0;
+ var $_error = '';
+
+ // Constructor:
+ function __construct($sql, $connectionID) {
+ $this->_sql = trim($sql);
+ $this->_connectionID = $connectionID;
+ $this->_result = $this->_connectionID->query($this->_sql);
+ if(!$this->_result) {
+ $this->_errno = $this->_connectionID->errno;
+ $this->_error = $this->_connectionID->error;
+ }
+ }
+
+ // Returns true if an error occured:
+ function error() {
+ // Returns true if the Result-ID is valid:
+ return !(bool)($this->_result);
+ }
+
+ // Returns an Error-String:
+ function getError() {
+ if($this->error()) {
+ $str = 'Query: ' .$this->_sql ."\n";
+ $str .= 'Error-Report: ' .$this->_error."\n";
+ $str .= 'Error-Code: '.$this->_errno;
+ } else {
+ $str = "No errors.";
+ }
+ return $str;
+ }
+
+ // Returns the content:
+ function fetch() {
+ if($this->error()) {
+ return null;
+ } else {
+ return $this->_result->fetch_assoc();
+ }
+ }
+
+ // Returns the number of rows (SELECT or SHOW):
+ function numRows() {
+ if($this->error()) {
+ return null;
+ } else {
+ return $this->_result->num_rows;
+ }
+ }
+
+ // Returns the number of affected rows (INSERT, UPDATE, REPLACE or DELETE):
+ function affectedRows() {
+ if($this->error()) {
+ return null;
+ } else {
+ return $this->_connectionID->affected_rows;
+ }
+ }
+
+ // Frees the memory:
+ function free() {
+ $this->_result->free();
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatString.php b/library/ajaxchat/chat/lib/class/AJAXChatString.php
new file mode 100644
index 000000000..8997da5ea
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatString.php
@@ -0,0 +1,37 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to provide multibyte enabled string methods
+class AJAXChatString {
+
+ public static function subString($str, $start=0, $length=null, $encoding='UTF-8') {
+ if($length === null) {
+ $length = AJAXChatString::stringLength($str);
+ }
+ if(function_exists('mb_substr')) {
+ return mb_substr($str, $start, $length, $encoding);
+ } else if(function_exists('iconv_substr')) {
+ return iconv_substr($str, $start, $length, $encoding);
+ } else {
+ return substr($str, $start, $length);
+ }
+ }
+
+ public static function stringLength($str, $encoding='UTF-8') {
+ if(function_exists('mb_strlen')) {
+ return mb_strlen($str, $encoding);
+ } else if(function_exists('iconv_strlen')) {
+ return iconv_strlen($str, $encoding);
+ } else {
+ return strlen($str);
+ }
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/AJAXChatTemplate.php b/library/ajaxchat/chat/lib/class/AJAXChatTemplate.php
new file mode 100644
index 000000000..16e53a7e6
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/AJAXChatTemplate.php
@@ -0,0 +1,329 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Class to handle HTML templates
+class AJAXChatTemplate {
+
+ var $ajaxChat;
+ var $_regExpTemplateTags;
+ var $_templateFile;
+ var $_contentType;
+ var $_content;
+ var $_parsedContent;
+
+ // Constructor:
+ function __construct(&$ajaxChat, $templateFile, $contentType=null) {
+ $this->ajaxChat = $ajaxChat;
+ $this->_regExpTemplateTags = '/\[(\w+?)(?:(?:\/)|(?:\](.+?)\[\/\1))\]/s';
+ $this->_templateFile = $templateFile;
+ $this->_contentType = $contentType;
+ }
+
+ function getParsedContent() {
+ if(!$this->_parsedContent) {
+ $this->parseContent();
+ }
+ return $this->_parsedContent;
+ }
+
+ function getContent() {
+ if(!$this->_content) {
+ $this->_content = AJAXChatFileSystem::getFileContents($this->_templateFile);
+ }
+ return $this->_content;
+ }
+
+ function parseContent() {
+ $this->_parsedContent = $this->getContent();
+
+ // Remove the XML declaration if the content-type is not xml:
+ if($this->_contentType && (strpos($this->_contentType,'xml') === false)) {
+ $doctypeStart = strpos($this->_parsedContent, '<!DOCTYPE ');
+ if($doctypeStart !== false) {
+ // Removing the XML declaration (in front of the document type) prevents IE<7 to go into "Quirks mode":
+ $this->_parsedContent = substr($this->_parsedContent, $doctypeStart);
+ }
+ }
+
+ // Replace template tags ([TAG/] and [TAG]content[/TAG]) and return parsed template content:
+ $this->_parsedContent = preg_replace_callback($this->_regExpTemplateTags, array($this, 'replaceTemplateTags'), $this->_parsedContent);
+ }
+
+ function replaceTemplateTags($tagData) {
+ switch($tagData[1]) {
+ case 'AJAX_CHAT_URL':
+ return $this->ajaxChat->htmlEncode($this->ajaxChat->getChatURL());
+
+ case 'LANG':
+ return $this->ajaxChat->htmlEncode($this->ajaxChat->getLang((isset($tagData[2]) ? $tagData[2] : null)));
+ case 'LANG_CODE':
+ return $this->ajaxChat->getLangCode();
+
+ case 'BASE_DIRECTION':
+ return $this->getBaseDirectionAttribute();
+
+ case 'CONTENT_ENCODING':
+ return $this->ajaxChat->getConfig('contentEncoding');
+
+ case 'CONTENT_TYPE':
+ return $this->_contentType;
+
+ case 'LOGIN_URL':
+ return ($this->ajaxChat->getRequestVar('view') == 'logs') ? './?view=logs' : './';
+
+ case 'USER_NAME_MAX_LENGTH':
+ return $this->ajaxChat->getConfig('userNameMaxLength');
+ case 'MESSAGE_TEXT_MAX_LENGTH':
+ return $this->ajaxChat->getConfig('messageTextMaxLength');
+
+ case 'LOGIN_CHANNEL_ID':
+ return $this->ajaxChat->getValidRequestChannelID();
+
+ case 'SESSION_NAME':
+ return $this->ajaxChat->getConfig('sessionName');
+
+ case 'COOKIE_EXPIRATION':
+ return $this->ajaxChat->getConfig('sessionCookieLifeTime');
+ case 'COOKIE_PATH':
+ return $this->ajaxChat->getConfig('sessionCookiePath');
+ case 'COOKIE_DOMAIN':
+ return $this->ajaxChat->getConfig('sessionCookieDomain');
+ case 'COOKIE_SECURE':
+ return $this->ajaxChat->getConfig('sessionCookieSecure');
+
+ case 'CHAT_BOT_NAME':
+ return rawurlencode($this->ajaxChat->getConfig('chatBotName'));
+ case 'CHAT_BOT_ID':
+ return $this->ajaxChat->getConfig('chatBotID');
+
+ case 'ALLOW_USER_MESSAGE_DELETE':
+ if($this->ajaxChat->getConfig('allowUserMessageDelete'))
+ return 1;
+ else
+ return 0;
+
+ case 'INACTIVE_TIMEOUT':
+ return $this->ajaxChat->getConfig('inactiveTimeout');
+
+ case 'PRIVATE_CHANNEL_DIFF':
+ return $this->ajaxChat->getConfig('privateChannelDiff');
+ case 'PRIVATE_MESSAGE_DIFF':
+ return $this->ajaxChat->getConfig('privateMessageDiff');
+
+ case 'SHOW_CHANNEL_MESSAGES':
+ if($this->ajaxChat->getConfig('showChannelMessages'))
+ return 1;
+ else
+ return 0;
+
+ case 'SOCKET_SERVER_ENABLED':
+ if($this->ajaxChat->getConfig('socketServerEnabled'))
+ return 1;
+ else
+ return 0;
+
+ case 'SOCKET_SERVER_HOST':
+ if($this->ajaxChat->getConfig('socketServerHost')) {
+ $socketServerHost = $this->ajaxChat->getConfig('socketServerHost');
+ } else {
+ $socketServerHost = (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']);
+ }
+ return rawurlencode($socketServerHost);
+
+ case 'SOCKET_SERVER_PORT':
+ return $this->ajaxChat->getConfig('socketServerPort');
+
+ case 'SOCKET_SERVER_CHAT_ID':
+ return $this->ajaxChat->getConfig('socketServerChatID');
+
+ case 'STYLE_SHEETS':
+ return $this->getStyleSheetLinkTags();
+
+ case 'CHANNEL_OPTIONS':
+ return $this->getChannelOptionTags();
+ case 'STYLE_OPTIONS':
+ return $this->getStyleOptionTags();
+ case 'LANGUAGE_OPTIONS':
+ return $this->getLanguageOptionTags();
+
+ case 'ERROR_MESSAGES':
+ return $this->getErrorMessageTags();
+
+ case 'LOGS_CHANNEL_OPTIONS':
+ return $this->getLogsChannelOptionTags();
+ case 'LOGS_YEAR_OPTIONS':
+ return $this->getLogsYearOptionTags();
+ case 'LOGS_MONTH_OPTIONS':
+ return $this->getLogsMonthOptionTags();
+ case 'LOGS_DAY_OPTIONS':
+ return $this->getLogsDayOptionTags();
+ case 'LOGS_HOUR_OPTIONS':
+ return $this->getLogsHourOptionTags();
+ case 'CLASS_WRITEABLE':
+ $userdata = $this->ajaxChat->getValidLoginUserData();
+ $guestwrite = $this->ajaxChat->getConfig('allowGuestWrite');
+ if ($userdata['userRole'] === AJAX_CHAT_GUEST && $guestwrite === false)
+ return 'write_forbidden';
+ else
+ return 'write_allowed';
+
+ default:
+ return $this->ajaxChat->replaceCustomTemplateTags($tagData[1], (isset($tagData[2]) ? $tagData[2] : null));
+ }
+ }
+
+ // Function to display alternating table row colors:
+ function alternateRow($rowOdd='rowOdd', $rowEven='rowEven') {
+ static $i;
+ $i += 1;
+ if($i % 2 == 0) {
+ return $rowEven;
+ } else {
+ return $rowOdd;
+ }
+ }
+
+ function getBaseDirectionAttribute() {
+ $langCodeParts = explode('-', $this->ajaxChat->getLangCode());
+ switch($langCodeParts[0]) {
+ case 'ar':
+ case 'fa':
+ case 'he':
+ return 'rtl';
+ default:
+ return 'ltr';
+ }
+ }
+
+ function getStyleSheetLinkTags() {
+ $styleSheets = '';
+ foreach($this->ajaxChat->getConfig('styleAvailable') as $style) {
+ $alternate = ($style == $this->ajaxChat->getConfig('styleDefault')) ? '' : 'alternate ';
+ $styleSheets .= '<link rel="'.$alternate.'stylesheet" type="text/css" href="css/'.rawurlencode($style).'.css" title="'.$this->ajaxChat->htmlEncode($style).'"/>';
+ }
+ return $styleSheets;
+ }
+
+ function getChannelOptionTags() {
+ $channelOptions = '';
+ $channelSelected = false;
+ foreach($this->ajaxChat->getChannels() as $name=>$id) {
+ if($this->ajaxChat->isLoggedIn() && $this->ajaxChat->getChannel()) {
+ $selected = ($id == $this->ajaxChat->getChannel()) ? ' selected="selected"' : '';
+ } else {
+ $selected = ($id == $this->ajaxChat->getConfig('defaultChannelID')) ? ' selected="selected"' : '';
+ }
+ if($selected) {
+ $channelSelected = true;
+ }
+ $channelOptions .= '<option value="'.$this->ajaxChat->htmlEncode($name).'"'.$selected.'>'.$this->ajaxChat->htmlEncode($name).'</option>';
+ }
+ if($this->ajaxChat->isLoggedIn() && $this->ajaxChat->isAllowedToCreatePrivateChannel()) {
+ // Add the private channel of the user to the options list:
+ if(!$channelSelected && $this->ajaxChat->getPrivateChannelID() == $this->ajaxChat->getChannel()) {
+ $selected = ' selected="selected"';
+ $channelSelected = true;
+ } else {
+ $selected = '';
+ }
+ $privateChannelName = $this->ajaxChat->getPrivateChannelName();
+ $channelOptions .= '<option value="'.$this->ajaxChat->htmlEncode($privateChannelName).'"'.$selected.'>'.$this->ajaxChat->htmlEncode($privateChannelName).'</option>';
+ }
+ // If current channel is not in the list, try to retrieve the channelName:
+ if(!$channelSelected) {
+ $channelName = $this->ajaxChat->getChannelName();
+ if($channelName !== null) {
+ $channelOptions .= '<option value="'.$this->ajaxChat->htmlEncode($channelName).'" selected="selected">'.$this->ajaxChat->htmlEncode($channelName).'</option>';
+ } else {
+ // Show an empty selection:
+ $channelOptions .= '<option value="" selected="selected">---</option>';
+ }
+ }
+ return $channelOptions;
+ }
+
+ function getStyleOptionTags() {
+ $styleOptions = '';
+ foreach($this->ajaxChat->getConfig('styleAvailable') as $style) {
+ $selected = ($style == $this->ajaxChat->getConfig('styleDefault')) ? ' selected="selected"' : '';
+ $styleOptions .= '<option value="'.$this->ajaxChat->htmlEncode($style).'"'.$selected.'>'.$this->ajaxChat->htmlEncode($style).'</option>';
+ }
+ return $styleOptions;
+ }
+
+ function getLanguageOptionTags() {
+ $languageOptions = '';
+ $languageNames = $this->ajaxChat->getConfig('langNames');
+ foreach($this->ajaxChat->getConfig('langAvailable') as $langCode) {
+ $selected = ($langCode == $this->ajaxChat->getLangCode()) ? ' selected="selected"' : '';
+ $languageOptions .= '<option value="'.$this->ajaxChat->htmlEncode($langCode).'"'.$selected.'>'.$languageNames[$langCode].'</option>';
+ }
+ return $languageOptions;
+ }
+
+ function getErrorMessageTags() {
+ $errorMessages = '';
+ foreach($this->ajaxChat->getInfoMessages('error') as $error) {
+ $errorMessages .= '<div>'.$this->ajaxChat->htmlEncode($this->ajaxChat->getLang($error)).'</div>';
+ }
+ return $errorMessages;
+ }
+
+ function getLogsChannelOptionTags() {
+ $channelOptions = '';
+ $channelOptions .= '<option value="-3">------</option>';
+ foreach($this->ajaxChat->getChannels() as $key=>$value) {
+ if($this->ajaxChat->getUserRole() != AJAX_CHAT_ADMIN && $this->ajaxChat->getConfig('logsUserAccessChannelList') && !in_array($value, $this->ajaxChat->getConfig('logsUserAccessChannelList'))) {
+ continue;
+ }
+ $channelOptions .= '<option value="'.$value.'">'.$this->ajaxChat->htmlEncode($key).'</option>';
+ }
+ $channelOptions .= '<option value="-1">'.$this->ajaxChat->htmlEncode($this->ajaxChat->getLang('logsPrivateChannels')).'</option>';
+ $channelOptions .= '<option value="-2">'.$this->ajaxChat->htmlEncode($this->ajaxChat->getLang('logsPrivateMessages')).'</option>';
+ return $channelOptions;
+ }
+
+ function getLogsYearOptionTags() {
+ $yearOptions = '';
+ $yearOptions .= '<option value="-1">----</option>';
+ for($year=date('Y'); $year>=$this->ajaxChat->getConfig('logsFirstYear'); $year--) {
+ $yearOptions .= '<option value="'.$year.'">'.$year.'</option>';
+ }
+ return $yearOptions;
+ }
+
+ function getLogsMonthOptionTags() {
+ $monthOptions = '';
+ $monthOptions .= '<option value="-1">--</option>';
+ for($month=1; $month<=12; $month++) {
+ $monthOptions .= '<option value="'.$month.'">'.sprintf("%02d", $month).'</option>';
+ }
+ return $monthOptions;
+ }
+
+ function getLogsDayOptionTags() {
+ $dayOptions = '';
+ $dayOptions .= '<option value="-1">--</option>';
+ for($day=1; $day<=31; $day++) {
+ $dayOptions .= '<option value="'.$day.'">'.sprintf("%02d", $day).'</option>';
+ }
+ return $dayOptions;
+ }
+
+ function getLogsHourOptionTags() {
+ $hourOptions = '';
+ $hourOptions .= '<option value="-1">-----</option>';
+ for($hour=0; $hour<=23; $hour++) {
+ $hourOptions .= '<option value="'.$hour.'">'.sprintf("%02d", $hour).':00</option>';
+ }
+ return $hourOptions;
+ }
+
+}
+?>
diff --git a/library/ajaxchat/chat/lib/class/CustomAJAXChat.php b/library/ajaxchat/chat/lib/class/CustomAJAXChat.php
new file mode 100644
index 000000000..a18e64069
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/CustomAJAXChat.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+class CustomAJAXChat extends AJAXChat {
+
+ // Returns an associative array containing userName, userID and userRole
+ // Returns null if login is invalid
+ function getValidLoginUserData() {
+
+ $customUsers = $this->getCustomUsers();
+
+ if($this->getRequestVar('password')) {
+ // Check if we have a valid registered user:
+
+ $userName = $this->getRequestVar('userName');
+ $userName = $this->convertEncoding($userName, $this->getConfig('contentEncoding'), $this->getConfig('sourceEncoding'));
+
+ $password = $this->getRequestVar('password');
+ $password = $this->convertEncoding($password, $this->getConfig('contentEncoding'), $this->getConfig('sourceEncoding'));
+
+ foreach($customUsers as $key=>$value) {
+ if(($value['userName'] == $userName) && ($value['password'] == $password)) {
+ $userData = array();
+ $userData['userID'] = $key;
+ $userData['userName'] = $this->trimUserName($value['userName']);
+ $userData['userRole'] = $value['userRole'];
+ return $userData;
+ }
+ }
+
+ return null;
+ } else {
+ // Guest users:
+ return $this->getGuestUser();
+ }
+ }
+
+ // Store the channels the current user has access to
+ // Make sure channel names don't contain any whitespace
+ function &getChannels() {
+ if($this->_channels === null) {
+ $this->_channels = array();
+
+ $customUsers = $this->getCustomUsers();
+
+ // Get the channels, the user has access to:
+ if($this->getUserRole() == AJAX_CHAT_GUEST) {
+ $validChannels = $customUsers[0]['channels'];
+ } else {
+ $validChannels = $customUsers[$this->getUserID()]['channels'];
+ }
+
+ // Add the valid channels to the channel list (the defaultChannelID is always valid):
+ foreach($this->getAllChannels() as $key=>$value) {
+ if ($value == $this->getConfig('defaultChannelID')) {
+ $this->_channels[$key] = $value;
+ continue;
+ }
+ // Check if we have to limit the available channels:
+ if($this->getConfig('limitChannelList') && !in_array($value, $this->getConfig('limitChannelList'))) {
+ continue;
+ }
+ if(in_array($value, $validChannels)) {
+ $this->_channels[$key] = $value;
+ }
+ }
+ }
+ return $this->_channels;
+ }
+
+ // Store all existing channels
+ // Make sure channel names don't contain any whitespace
+ function &getAllChannels() {
+ if($this->_allChannels === null) {
+ // Get all existing channels:
+ $customChannels = $this->getCustomChannels();
+
+ $defaultChannelFound = false;
+
+ foreach($customChannels as $name=>$id) {
+ $this->_allChannels[$this->trimChannelName($name)] = $id;
+ if($id == $this->getConfig('defaultChannelID')) {
+ $defaultChannelFound = true;
+ }
+ }
+
+ if(!$defaultChannelFound) {
+ // Add the default channel as first array element to the channel list
+ // First remove it in case it appeard under a different ID
+ unset($this->_allChannels[$this->getConfig('defaultChannelName')]);
+ $this->_allChannels = array_merge(
+ array(
+ $this->trimChannelName($this->getConfig('defaultChannelName'))=>$this->getConfig('defaultChannelID')
+ ),
+ $this->_allChannels
+ );
+ }
+ }
+ return $this->_allChannels;
+ }
+
+ function &getCustomUsers() {
+ // List containing the registered chat users:
+ $users = null;
+ require(AJAX_CHAT_PATH.'lib/data/users.php');
+ return $users;
+ }
+
+ function getCustomChannels() {
+ // List containing the custom channels:
+ $channels = null;
+ require(AJAX_CHAT_PATH.'lib/data/channels.php');
+ // Channel array structure should be:
+ // ChannelName => ChannelID
+ return array_flip($channels);
+ }
+
+} \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/CustomAJAXChatInterface.php b/library/ajaxchat/chat/lib/class/CustomAJAXChatInterface.php
new file mode 100644
index 000000000..a950739c5
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/CustomAJAXChatInterface.php
@@ -0,0 +1,21 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+class CustomAJAXChatInterface extends CustomAJAXChat {
+
+ function initialize() {
+ // Initialize configuration settings:
+ $this->initConfig();
+
+ // Initialize the DataBase connection:
+ $this->initDataBaseConnection();
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/class/CustomAJAXChatShoutBox.php b/library/ajaxchat/chat/lib/class/CustomAJAXChatShoutBox.php
new file mode 100644
index 000000000..c014d639e
--- /dev/null
+++ b/library/ajaxchat/chat/lib/class/CustomAJAXChatShoutBox.php
@@ -0,0 +1,25 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+class CustomAJAXChatShoutBox extends CustomAJAXChat {
+
+ function initialize() {
+ // Initialize configuration settings:
+ $this->initConfig();
+ }
+
+ function getShoutBoxContent() {
+ $template = new AJAXChatTemplate($this, AJAX_CHAT_PATH.'lib/template/shoutbox.html');
+
+ // Return parsed template content:
+ return $template->getParsedContent();
+ }
+
+}
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/classes.php b/library/ajaxchat/chat/lib/classes.php
new file mode 100644
index 000000000..ff1dee265
--- /dev/null
+++ b/library/ajaxchat/chat/lib/classes.php
@@ -0,0 +1,26 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Include Class libraries:
+require(AJAX_CHAT_PATH.'lib/class/AJAXChat.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatDataBase.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatMySQLDataBase.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatMySQLQuery.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatMySQLiDataBase.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatMySQLiQuery.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatEncoding.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatString.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatFileSystem.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatHTTPHeader.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatLanguage.php');
+require(AJAX_CHAT_PATH.'lib/class/AJAXChatTemplate.php');
+require(AJAX_CHAT_PATH.'lib/class/CustomAJAXChat.php');
+require(AJAX_CHAT_PATH.'lib/class/CustomAJAXChatShoutBox.php');
+require(AJAX_CHAT_PATH.'lib/class/CustomAJAXChatInterface.php');
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/config.php.example b/library/ajaxchat/chat/lib/config.php.example
new file mode 100644
index 000000000..023adcdbb
--- /dev/null
+++ b/library/ajaxchat/chat/lib/config.php.example
@@ -0,0 +1,209 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Define AJAX Chat user roles:
+define('AJAX_CHAT_CHATBOT', 4);
+define('AJAX_CHAT_ADMIN', 3);
+define('AJAX_CHAT_MODERATOR', 2);
+define('AJAX_CHAT_USER', 1);
+define('AJAX_CHAT_GUEST', 0);
+
+// AJAX Chat config parameters:
+$config = array();
+
+// Database connection values:
+$config['dbConnection'] = array();
+// Database hostname:
+$config['dbConnection']['host'] = 'localhost';
+// Database username:
+$config['dbConnection']['user'] = 'root';
+// Database password:
+$config['dbConnection']['pass'] = '';
+// Database name:
+$config['dbConnection']['name'] = 'chat';
+// Database type:
+$config['dbConnection']['type'] = null;
+// Database link:
+$config['dbConnection']['link'] = null;
+
+// Database table names:
+$config['dbTableNames'] = array();
+$config['dbTableNames']['online'] = 'ajax_chat_online';
+$config['dbTableNames']['messages'] = 'ajax_chat_messages';
+$config['dbTableNames']['bans'] = 'ajax_chat_bans';
+$config['dbTableNames']['invitations'] = 'ajax_chat_invitations';
+
+// Available languages:
+$config['langAvailable'] = array(
+ 'ar','bg','ca','cy','cz','da','de','el','en','es','et','fa','fi','fr','gl','he','hr','hu','in','it','ja','ka','kr','mk','nl','nl-be','no','pl','pt-br','pt-pt','ro','ru','sk','sl','sr','sv','th','tr','uk','zh','zh-tw'
+);
+// Default language:
+$config['langDefault'] = 'en';
+// Language names (each languge code in available languages must have a display name assigned here):
+$config['langNames'] = array(
+ 'ar'=>'عربي', 'bg'=>'Български', 'ca'=>'Català', 'cy'=>'Cymraeg', 'cz'=>'Česky', 'da'=>'Dansk', 'de'=>'Deutsch', 'el'=>'Ελληνικα', 'en'=>'English',
+ 'es'=>'Español', 'et'=>'Eesti', 'fa'=>'فارسی', 'fi'=>'Suomi', 'fr'=>'Français', 'gl'=>'Galego', 'he'=>'עברית', 'hr' => 'Hrvatski', 'hu' => 'Magyar', 'in'=>'Bahasa Indonesia', 'it'=>'Italiano',
+ 'ja'=>'日本語','ka'=>'ქართული','kr'=>'한 글','mk'=>'Македонски', 'nl'=>'Nederlands', 'nl-be'=>'Nederlands (België)', 'no'=>'Norsk', 'pl'=> 'Polski', 'pt-br'=>'Português (Brasil)', 'pt-pt'=>'Português (Portugal)',
+ 'ro'=>'România', 'ru'=>'Русский', 'sk'=> 'Slovenčina', 'sl'=>'Slovensko', 'sr'=>'Srpski', 'sv'=> 'Svenska', 'th'=>'&#x0e20;&#x0e32;&#x0e29;&#x0e32;&#x0e44;&#x0e17;&#x0e22;',
+ 'tr'=>'Türkçe', 'uk'=>'Українська', 'zh'=>'中文 (简体)', 'zh-tw'=>'中文 (繁體)'
+);
+
+// Available styles:
+$config['styleAvailable'] = array('beige','black','grey','Oxygen','Lithium','Sulfur','Cobalt','Mercury','Uranium','Plum','prosilver','subblack2','subSilver','Core','MyBB','vBulletin');
+// Default style:
+$config['styleDefault'] = 'prosilver';
+
+// The encoding used for the XHTML content:
+$config['contentEncoding'] = 'UTF-8';
+// The encoding of the data source, like userNames and channelNames:
+$config['sourceEncoding'] = 'UTF-8';
+// The content-type of the XHTML page (e.g. "text/html", will be set dependent on browser capabilities if set to null):
+$config['contentType'] = null;
+
+// Session name used to identify the session cookie:
+$config['sessionName'] = 'ajax_chat';
+// Prefix added to every session key:
+$config['sessionKeyPrefix'] = 'ajaxChat';
+// The lifetime of the language, style and setting cookies in days:
+$config['sessionCookieLifeTime'] = 365;
+// The path of the cookies, '/' allows to read the cookies from all directories:
+$config['sessionCookiePath'] = '/';
+// The domain of the cookies, defaults to the hostname of the server if set to null:
+$config['sessionCookieDomain'] = null;
+// If enabled, cookies must be sent over secure (SSL/TLS encrypted) connections:
+$config['sessionCookieSecure'] = null;
+
+// Default channelName used together with the defaultChannelID if no channel with this ID exists:
+$config['defaultChannelName'] = 'Public';
+// ChannelID used when no channel is given:
+$config['defaultChannelID'] = 0;
+// Defines an array of channelIDs (e.g. array(0, 1)) to limit the number of available channels, will be ignored if set to null:
+$config['limitChannelList'] = null;
+
+// UserID plus this value are private channels (this is also the max userID and max channelID):
+$config['privateChannelDiff'] = 500000000;
+// UserID plus this value are used for private messages:
+$config['privateMessageDiff'] = 1000000000;
+
+// Enable/Disable private Channels:
+$config['allowPrivateChannels'] = true;
+// Enable/Disable private Messages:
+$config['allowPrivateMessages'] = true;
+
+// Private channels should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['privateChannelPrefix'] = '[';
+// Private channels should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['privateChannelSuffix'] = ']';
+
+// If enabled, users will be logged in automatically as guest users (if allowed), if not authenticated:
+$config['forceAutoLogin'] = false;
+
+// Defines if login/logout and channel enter/leave are displayed:
+$config['showChannelMessages'] = true;
+
+// If enabled, the chat will only be accessible for the admin:
+$config['chatClosed'] = false;
+// Defines the timezone offset in seconds (-12*60*60 to 12*60*60) - if null, the server timezone is used:
+$config['timeZoneOffset'] = null;
+// Defines the hour of the day the chat is opened (0 - closingHour):
+$config['openingHour'] = 0;
+// Defines the hour of the day the chat is closed (openingHour - 24):
+$config['closingHour'] = 24;
+// Defines the weekdays the chat is opened (0=Sunday to 6=Saturday):
+$config['openingWeekDays'] = array(0,1,2,3,4,5,6);
+
+// Enable/Disable guest logins:
+$config['allowGuestLogins'] = true;
+// Enable/Disable write access for guest users - if disabled, guest users may not write messages:
+$config['allowGuestWrite'] = true;
+// Allow/Disallow guest users to choose their own userName:
+$config['allowGuestUserName'] = true;
+// Guest users should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['guestUserPrefix'] = '(';
+// Guest users should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['guestUserSuffix'] = ')';
+// Guest userIDs may not be lower than this value (and not higher than privateChannelDiff):
+$config['minGuestUserID'] = 400000000;
+
+// Allow/Disallow users to change their userName (Nickname):
+$config['allowNickChange'] = true;
+// Changed userNames should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['changedNickPrefix'] = '(';
+// Changed userNames should be distinguished by either a prefix or a suffix or both (no whitespace):
+$config['changedNickSuffix'] = ')';
+
+// Allow/Disallow registered users to delete their own messages:
+$config['allowUserMessageDelete'] = true;
+
+// The userID used for ChatBot messages:
+$config['chatBotID'] = 2147483647;
+// The userName used for ChatBot messages
+$config['chatBotName'] = 'ChatBot';
+
+// Minutes until a user is declared inactive (last status update) - the minimum is 2 minutes:
+$config['inactiveTimeout'] = 2;
+// Interval in minutes to check for inactive users:
+$config['inactiveCheckInterval'] = 5;
+
+// Defines if messages are shown which have been sent before the user entered the channel:
+$config['requestMessagesPriorChannelEnter'] = true;
+// Defines an array of channelIDs (e.g. array(0, 1)) for which the previous setting is always true (will be ignored if set to null):
+$config['requestMessagesPriorChannelEnterList'] = null;
+// Max time difference in hours for messages to display on each request:
+$config['requestMessagesTimeDiff'] = 24;
+// Max number of messages to display on each request:
+$config['requestMessagesLimit'] = 10;
+
+// Max users in chat (does not affect moderators or admins):
+$config['maxUsersLoggedIn'] = 100;
+// Max userName length:
+$config['userNameMaxLength'] = 16;
+// Max messageText length:
+$config['messageTextMaxLength'] = 1040;
+// Defines the max number of messages a user may send per minute:
+$config['maxMessageRate'] = 20;
+
+// Defines the default time in minutes a user gets banned if kicked from a moderator without ban minutes parameter:
+$config['defaultBanTime'] = 5;
+
+// Argument that is given to the handleLogout JavaScript method:
+$config['logoutData'] = './?logout=true';
+
+// If true, checks if the user IP is the same when logged in:
+$config['ipCheck'] = true;
+
+// Defines the max time difference in hours for logs when no period or search condition is given:
+$config['logsRequestMessagesTimeDiff'] = 1;
+// Defines how many logs are returned on each logs request:
+$config['logsRequestMessagesLimit'] = 10;
+
+// Defines the earliest year used for the logs selection:
+$config['logsFirstYear'] = 2007;
+
+// Defines if old messages are purged from the database:
+$config['logsPurgeLogs'] = false;
+// Max time difference in days for old messages before they are purged from the database:
+$config['logsPurgeTimeDiff'] = 365;
+
+// Defines if registered users (including moderators) have access to the logs (admins are always granted access):
+$config['logsUserAccess'] = false;
+// Defines a list of channels (e.g. array(0, 1)) to limit the logs access for registered users, includes all channels the user has access to if set to null:
+$config['logsUserAccessChannelList'] = null;
+
+// Defines if the socket server is enabled:
+$config['socketServerEnabled'] = false;
+// Defines the hostname of the socket server used to connect from client side (the server hostname is used if set to null):
+$config['socketServerHost'] = null;
+// Defines the IP of the socket server used to connect from server side to broadcast update messages:
+$config['socketServerIP'] = '127.0.0.1';
+// Defines the port of the socket server:
+$config['socketServerPort'] = 1935;
+// This ID can be used to distinguish between different chat installations using the same socket server:
+$config['socketServerChatID'] = 0;
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/custom.php b/library/ajaxchat/chat/lib/custom.php
new file mode 100644
index 000000000..a9d08841b
--- /dev/null
+++ b/library/ajaxchat/chat/lib/custom.php
@@ -0,0 +1,11 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// Include custom libraries and initialization code here
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/data/channels.php b/library/ajaxchat/chat/lib/data/channels.php
new file mode 100644
index 000000000..8688e5e7b
--- /dev/null
+++ b/library/ajaxchat/chat/lib/data/channels.php
@@ -0,0 +1,16 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// List containing the custom channels:
+$channels = array();
+
+// Sample channel list:
+$channels[0] = 'Public';
+$channels[1] = 'Private';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/data/users.php b/library/ajaxchat/chat/lib/data/users.php
new file mode 100644
index 000000000..52ca77e50
--- /dev/null
+++ b/library/ajaxchat/chat/lib/data/users.php
@@ -0,0 +1,40 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+// List containing the registered chat users:
+$users = array();
+
+// Default guest user (don't delete this one):
+$users[0] = array();
+$users[0]['userRole'] = AJAX_CHAT_GUEST;
+$users[0]['userName'] = null;
+$users[0]['password'] = null;
+$users[0]['channels'] = array(0);
+
+// Sample admin user:
+$users[1] = array();
+$users[1]['userRole'] = AJAX_CHAT_ADMIN;
+$users[1]['userName'] = 'admin';
+$users[1]['password'] = 'admin';
+$users[1]['channels'] = array(0,1);
+
+// Sample moderator user:
+$users[2] = array();
+$users[2]['userRole'] = AJAX_CHAT_MODERATOR;
+$users[2]['userName'] = 'moderator';
+$users[2]['password'] = 'moderator';
+$users[2]['channels'] = array(0,1);
+
+// Sample registered user:
+$users[3] = array();
+$users[3]['userRole'] = AJAX_CHAT_USER;
+$users[3]['userName'] = 'user';
+$users[3]['password'] = 'user';
+$users[3]['channels'] = array(0,1);
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ar.php b/library/ajaxchat/chat/lib/lang/ar.php
new file mode 100644
index 000000000..af9c8305e
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ar.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author pepotiger (www.dd4bb.com)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'اسم المستخدم';
+$lang['password'] = 'كلمة المرور';
+$lang['login'] = 'دخول';
+$lang['logout'] = 'خروج';
+$lang['channel'] = 'الغرفة';
+$lang['style'] = 'الشكل';
+$lang['language'] = 'اللغة';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'ارسل';
+$lang['registeredUsers'] = 'الأعضاء المسجلين';
+$lang['onlineUsers'] = 'الأعضاء المتواجدين';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'اقتباس';
+$lang['bbCodeLabelCode'] = 'كود';
+$lang['bbCodeLabelURL'] = 'رابط';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'لون الخط';
+$lang['bbCodeTitleBold'] = 'نص عريض: [b]نص[/b]';
+$lang['bbCodeTitleItalic'] = 'نص مائل: [i]نص[/i]';
+$lang['bbCodeTitleUnderline'] = 'نص تحته خط: [u]نص[/u]';
+$lang['bbCodeTitleQuote'] = 'نص مقتبس: [quote]نص[/quote] او [quote=الكاتب]نص[/quote]';
+$lang['bbCodeTitleCode'] = 'عرض الكود: [code]كود[/code]';
+$lang['bbCodeTitleURL'] = 'ادحال رابط: [url]http://example.org[/url] او [url=http://example.org]نص[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'لون النص: [color=red]نص[/color]';
+$lang['help'] = 'مساعدة';
+$lang['helpItemDescJoin'] = 'دخول الغرفة:';
+$lang['helpItemCodeJoin'] = '/join اسم الغرفة';
+$lang['helpItemDescJoinCreate'] = 'انشاء غرفة خاصة (للمسجلين فقط):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'دعوة احد (لغرفة خاصة مثلا):';
+$lang['helpItemCodeInvite'] = '/invite username';
+$lang['helpItemDescUninvite'] = 'الغاء الدعوة:';
+$lang['helpItemCodeUninvite'] = '/uninvite Username';
+$lang['helpItemDescLogout'] = 'خروج:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'رسالة خاصة:';
+$lang['helpItemCodePrivateMessage'] = '/msg Username نص';
+$lang['helpItemDescQueryOpen'] = 'فتح نافذة خاصة:';
+$lang['helpItemCodeQueryOpen'] = '/query Username';
+$lang['helpItemDescQueryClose'] = 'غلق النافذة الخاصة:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'وصف الحدث:';
+$lang['helpItemCodeAction'] = '/action نص';
+$lang['helpItemDescDescribe'] = 'وصف حدث برسالة خاصة:';
+$lang['helpItemCodeDescribe'] = '/describe Username نص';
+$lang['helpItemDescIgnore'] = 'تجاهل/قبول رسائل خاصة من:';
+$lang['helpItemCodeIgnore'] = '/ignore Username';
+$lang['helpItemDescIgnoreList'] = 'الأعضاء المتجاهلين:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'حظر مستخدمين (للمديرين فقط):';
+$lang['helpItemCodeKick'] = '/kick Username [دقائق الحظر]';
+$lang['helpItemDescUnban'] = 'الغاء حظر عضو (للمديرين فقط):';
+$lang['helpItemCodeUnban'] = '/unban Username';
+$lang['helpItemDescBans'] = 'الأعضاء المحظورين (للمديرين فقط):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'عرض الأى بى للمستخدم (المديرين فقط):';
+$lang['helpItemCodeWhois'] = '/whois Username';
+$lang['helpItemDescWho'] = 'الأعضاء المتواجدين:';
+$lang['helpItemCodeWho'] = '/who [Channelname]';
+$lang['helpItemDescList'] = 'القنوات المتوافرة:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Roll dice:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'يجب دعم الجافة سكريبت لهذا الشات.';
+$lang['errorInvalidUser'] = 'اسم مستخدم خطأ.';
+$lang['errorUserInUse'] = 'اسم المستخدم مستخدم.';
+$lang['errorBanned'] = 'المستخدم او عنوان الأى بى محظور.';
+$lang['errorMaxUsersLoggedIn'] = 'الشات به الحد الأقصى من الأعضاء المسجلين.';
+$lang['errorChatClosed'] = 'الشات مغلق حاليا.';
+$lang['logsTitle'] = 'سحل الشات';
+$lang['logsDate'] = 'التاريخ';
+$lang['logsTime'] = 'الوقت';
+$lang['logsSearch'] = 'بحث';
+$lang['logsPrivateChannels'] = 'القنوات الخاصة';
+$lang['logsPrivateMessages'] = 'الرسائل الخاصة';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/bg.php b/library/ajaxchat/chat/lib/lang/bg.php
new file mode 100644
index 000000000..46d6af163
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/bg.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Borislav Manolov
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Потребителско име';
+$lang['password'] = 'Парола';
+$lang['login'] = 'Вход';
+$lang['logout'] = 'Изход';
+$lang['channel'] = 'Канал';
+$lang['style'] = 'Облик';
+$lang['language'] = 'Език';
+$lang['inputLineBreak'] = 'Натиснете SHIFT+ENTER, за да вмъкнете нов ред';
+$lang['messageSubmit'] = 'Пращане';
+$lang['registeredUsers'] = 'Регистрирани потребители';
+$lang['onlineUsers'] = 'Потребители на линия';
+$lang['toggleAutoScroll'] = 'Автопрелистване вкл/изкл';
+$lang['toggleAudio'] = 'Звук вкл/изкл';
+$lang['toggleHelp'] = 'Показване/скриване на помощта';
+$lang['toggleSettings'] = 'Показване/скриване на настройките';
+$lang['toggleOnlineList'] = 'Показване/скриване на списъка с потребителите';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Цитат';
+$lang['bbCodeLabelCode'] = 'Код';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Картинка';
+$lang['bbCodeLabelColor'] = 'Цвят на шрифта';
+$lang['bbCodeTitleBold'] = 'Получер текст: [b]текст[/b]';
+$lang['bbCodeTitleItalic'] = 'Курсивен текст: [i]текст[/i]';
+$lang['bbCodeTitleUnderline'] = 'Подчертан текст: [u]текст[/u]';
+$lang['bbCodeTitleQuote'] = 'Цитиран текст: [quote]текст[/quote] или [quote=Автор]текст[/quote]';
+$lang['bbCodeTitleCode'] = 'Показване на код: [code]код[/code]';
+$lang['bbCodeTitleURL'] = 'URL: [url]http://example.org[/url] или [url=http://example.org]текст[/url]';
+$lang['bbCodeTitleImg'] = 'Вмъкване на картинка: [img]http://primer.org/kartinka.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Цвят на шрифта: [color=red]текст[/color]';
+$lang['help'] = 'Помощ';
+$lang['helpItemDescJoin'] = 'Присъединяване към канал:';
+$lang['helpItemCodeJoin'] = '/join име_на_канал';
+$lang['helpItemDescJoinCreate'] = 'Създаване на лична стая (само за регистрирани потребители):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Покана на потребител (напр. в лична стая):';
+$lang['helpItemCodeInvite'] = '/invite Потребителско_име';
+$lang['helpItemDescUninvite'] = 'Отказване на покана:';
+$lang['helpItemCodeUninvite'] = '/uninvite Потребителско_име';
+$lang['helpItemDescLogout'] = 'Изход от чата:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Лично съобщение:';
+$lang['helpItemCodePrivateMessage'] = '/msg Потребителско_име Текст';
+$lang['helpItemDescQueryOpen'] = 'Отваряне на личен канал:';
+$lang['helpItemCodeQueryOpen'] = '/query Потребителско_име';
+$lang['helpItemDescQueryClose'] = 'Затваряне на личен канал:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Описание на действие:';
+$lang['helpItemCodeAction'] = '/action Текст';
+$lang['helpItemDescDescribe'] = 'Описание на действието в лично съобщение:';
+$lang['helpItemCodeDescribe'] = '/describe Потребителско_име Текст';
+$lang['helpItemDescIgnore'] = 'Пренебрегване/приемане на съобщения от потребител:';
+$lang['helpItemCodeIgnore'] = '/ignore Потребителско_име';
+$lang['helpItemDescIgnoreList'] = 'Преглед на пренебрегнатите потребители:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Показване на потребителския канал:';
+$lang['helpItemCodeWhereis'] = '/whereis Потребителско_име';
+$lang['helpItemDescKick'] = 'Изритване на потребител (само за модератори):';
+$lang['helpItemCodeKick'] = '/kick Потребителско_име [брой минути]';
+$lang['helpItemDescUnban'] = 'Изгонване на потребител (само за модератори):';
+$lang['helpItemCodeUnban'] = '/unban Потребителско_име';
+$lang['helpItemDescBans'] = 'Преглед на изгонените потребители (само за модератори):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Преглед на айпи адреса на потребител (само за модератори):';
+$lang['helpItemCodeWhois'] = '/whois Потребителско_име';
+$lang['helpItemDescWho'] = 'Преглед на потребителите на линия:';
+$lang['helpItemCodeWho'] = '/who [Име_на_канал]';
+$lang['helpItemDescList'] = 'Преглед на наличните канали:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Хвърляне на зар:';
+$lang['helpItemCodeRoll'] = '/roll [пъти]d[страни]';
+$lang['helpItemDescNick'] = 'Смяна на потребителско име:';
+$lang['helpItemCodeNick'] = '/nick Потребителско_име';
+$lang['settings'] = 'Настройки';
+$lang['settingsBBCode'] = 'Позволяване на BBCode:';
+$lang['settingsBBCodeImages'] = 'Позволяване на BBCode за картинки:';
+$lang['settingsBBCodeColors'] = 'Позволяване на BBCode за шрифтов цвят:';
+$lang['settingsHyperLinks'] = 'Позволяване на хипервръзки:';
+$lang['settingsLineBreaks'] = 'Позволяване на край на ред:';
+$lang['settingsEmoticons'] = 'Позволяване на усмивки:';
+$lang['settingsAutoFocus'] = 'Автоматично фокусиране на полето за въвеждане:';
+$lang['settingsMaxMessages'] = 'Максимален брой съобщения в прозореца на чата:';
+$lang['settingsWordWrap'] = 'Пренасяне на дълги думи:';
+$lang['settingsMaxWordLength'] = 'Максимална дължина на дума преди да бъде пренесена:';
+$lang['settingsDateFormat'] = 'Формат на датата и часа:';
+$lang['settingsPersistFontColor'] = 'Устойчив цвят на шрифта:';
+$lang['settingsAudioVolume'] = 'Височина на звука:';
+$lang['settingsSoundReceive'] = 'Звук за входящи съобщения:';
+$lang['settingsSoundSend'] = 'Звук за изходящи съобщения:';
+$lang['settingsSoundEnter'] = 'Звук за съобщенията за влизане в чата или в канала:';
+$lang['settingsSoundLeave'] = 'Звук за съобщенията за излизане от чата или от канала:';
+$lang['settingsSoundChatBot'] = 'Звук за съобщенията на чатбота:';
+$lang['settingsSoundError'] = 'Звук за съобщенията за грешки:';
+$lang['settingsBlink'] = 'Примигване на прозоречното заглавие при нови съобщения:';
+$lang['settingsBlinkInterval'] = 'Интервал на примигване в милисекунди:';
+$lang['settingsBlinkIntervalNumber'] = 'Брой пъти на примигване:';
+$lang['playSelectedSound'] = 'Прослушване на избрания звук';
+$lang['requiresJavaScript'] = 'За чата се изисква поддръжката на Джаваскрипт.';
+$lang['errorInvalidUser'] = 'Грешно потребителско име.';
+$lang['errorUserInUse'] = 'Потребителското име се използва.';
+$lang['errorBanned'] = 'Потребителят или айпи адресът е изгонен.';
+$lang['errorMaxUsersLoggedIn'] = 'Чатът достигна максималния брой на влезли потребители.';
+$lang['errorChatClosed'] = 'В момента чатът е затворен.';
+$lang['logsTitle'] = 'AJAX Chat — Логове';
+$lang['logsDate'] = 'Дата';
+$lang['logsTime'] = 'Време';
+$lang['logsSearch'] = 'Търсене';
+$lang['logsPrivateChannels'] = 'Лични канали';
+$lang['logsPrivateMessages'] = 'Лични съобщения';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ca.php b/library/ajaxchat/chat/lib/lang/ca.php
new file mode 100644
index 000000000..e45c376da
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ca.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Manu Quintans
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Usuari';
+$lang['password'] = 'Contrasenya';
+$lang['login'] = 'Accedir';
+$lang['logout'] = 'Tancar sessió';
+$lang['channel'] = 'Canal';
+$lang['style'] = 'Estil';
+$lang['language'] = 'Idioma';
+$lang['inputLineBreak'] = 'Prem SHIFT+ENTER per introduir un salt de línia';
+$lang['messageSubmit'] = 'Enviar';
+$lang['registeredUsers'] = 'Usuaris registrats';
+$lang['onlineUsers'] = 'Usuaris Conectats';
+$lang['toggleAutoScroll'] = 'Desplaçament automàtic activat/desactivat';
+$lang['toggleAudio'] = 'So activat/desactivat';
+$lang['toggleHelp'] = 'mostra/amaga ajuda';
+$lang['toggleSettings'] = 'mostra/amaga propietats';
+$lang['toggleOnlineList'] = 'mostra/amaga usuaris conectats';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citar';
+$lang['bbCodeLabelCode'] = 'Codi';
+$lang['bbCodeLabelURL'] = 'Enllaç';
+$lang['bbCodeLabelImg'] = 'Imatge';
+$lang['bbCodeLabelColor'] = 'Color de la Font';
+$lang['bbCodeTitleBold'] = 'text en negreta: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'text en cursiva: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'text subratllat: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'text citat: [quote]text[/quote] o [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Mostrar codi: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Insertar enllaç: [url]http://example.org[/url] o [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insertar imatge: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Color de la font: [color=red]text[/color]';
+$lang['help'] = 'Ajuda';
+$lang['helpItemDescJoin'] = 'Entrar en canal:';
+$lang['helpItemCodeJoin'] = '/join nom del canal';
+$lang['helpItemDescJoinCreate'] = 'Crear una sala privada (només usuaris registrats):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Convidar algú (p.ex. a una sala privada):';
+$lang['helpItemCodeInvite'] = '/invite nom de l\'usuari';
+$lang['helpItemDescUninvite'] = 'Cancel·lar invitació:';
+$lang['helpItemCodeUninvite'] = '/uninvite nom d l\'usuari';
+$lang['helpItemDescLogout'] = 'Tancar sessió:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Missatge privat:';
+$lang['helpItemCodePrivateMessage'] = '/msg Usuari Text';
+$lang['helpItemDescQueryOpen'] = 'Obrir un canal privat:';
+$lang['helpItemCodeQueryOpen'] = '/query Usuari';
+$lang['helpItemDescQueryClose'] = 'Tancar canal privat:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Descriu acció:';
+$lang['helpItemCodeAction'] = '/action acció';
+$lang['helpItemDescDescribe'] = 'Descriu acció en un missatge privat:';
+$lang['helpItemCodeDescribe'] = '/describe NomUsuari acció';
+$lang['helpItemDescIgnore'] = 'Ignorar/Acceptar missatges d\'usuaris:';
+$lang['helpItemCodeIgnore'] = '/ignore nom de l\'usuari ';
+$lang['helpItemDescIgnoreList'] = 'Llista d\'usuaris ignorats:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Mostra canal de l\'usuari:';
+$lang['helpItemCodeWhereis'] = '/whereis nom de l\'usuari';
+$lang['helpItemDescKick'] = 'Patear usuari (només moderadors):';
+$lang['helpItemCodeKick'] = '/kick Usuari [Minuts banejat]';
+$lang['helpItemDescUnban'] = 'treure banejat usuari (només moderadors):';
+$lang['helpItemCodeUnban'] = '/unban nom de l\'usuari';
+$lang['helpItemDescBans'] = 'Llista d\'usuaris banejats (només moderadors):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Mostrar les IPs d\'usuaris (només moderadors):';
+$lang['helpItemCodeWhois'] = '/whois nom de l\'usuari';
+$lang['helpItemDescWho'] = 'Mostrar usuaris conectats:';
+$lang['helpItemCodeWho'] = '/who [nom del canal]';
+$lang['helpItemDescList'] = 'Llista de canals disponibles:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Tirar els daus:';
+$lang['helpItemCodeRoll'] = '/roll [nombre]d[cares]';
+$lang['helpItemDescNick'] = 'canviar nom d\'usuari:';
+$lang['helpItemCodeNick'] = '/nick nom d\'usuari';
+$lang['settings'] = 'Configuració';
+$lang['settingsBBCode'] = 'Habilitar BBCode:';
+$lang['settingsBBCodeImages'] = 'Habilitar imatge BBCode:';
+$lang['settingsBBCodeColors'] = 'habilitar color de font BBCode:';
+$lang['settingsHyperLinks'] = 'habilitar hipervincles:';
+$lang['settingsLineBreaks'] = 'Habilitar salts de línia:';
+$lang['settingsEmoticons'] = 'Habilitar emoticons:';
+$lang['settingsAutoFocus'] = 'Configurar automàticament el focus en el camp d\'entrada:';
+$lang['settingsMaxMessages'] = 'Màxim nombre de missatges en les llistes de Xat:';
+$lang['settingsWordWrap'] = 'Habilitar partir paraules llargues';
+$lang['settingsMaxWordLength'] = 'Màxima llargada d\'una paraula abns de ser tallada:';
+$lang['settingsDateFormat'] = 'Format de dia i hora:';
+$lang['settingsPersistFontColor'] = 'Color de font persistent:';
+$lang['settingsAudioVolume'] = 'So volum:';
+$lang['settingsSoundReceive'] = 'So per missatdes d\'entrada:';
+$lang['settingsSoundSend'] = 'So per missatges de sortida:';
+$lang['settingsSoundEnter'] = 'So per connectar i missatges d\'entrada del canal:';
+$lang['settingsSoundLeave'] = 'So per desconnectar i missatges de sortida del canal:';
+$lang['settingsSoundChatBot'] = 'So pels missatges del xat:';
+$lang['settingsSoundError'] = 'So per missatges d\'error:';
+$lang['settingsBlink'] = 'Notificació de finestra per als nous missatges:';
+$lang['settingsBlinkInterval'] = 'Interval de notificacions intermitents (milisegons):';
+$lang['settingsBlinkIntervalNumber'] = 'Nombre de notificacions intermitents:';
+$lang['playSelectedSound'] = 'Reproduir el so seleccionat';
+$lang['requiresJavaScript'] = 'Necesites tenir instal·lat Javascript al teu navegador';
+$lang['errorInvalidUser'] = 'Usuari no vàlid';
+$lang['errorUserInUse'] = 'Aquest nom d\'usuari està sent utilitzat en aquests moments';
+$lang['errorBanned'] = 'L\'usuari o IP està bannejat';
+$lang['errorMaxUsersLoggedIn'] = 'El xat ha arribat al màxim nombre d\'usuaris.';
+$lang['errorChatClosed'] = 'El xat està tancat en aquests moments.';
+$lang['logsTitle'] = 'AJAX Xat - Registre';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Hora';
+$lang['logsSearch'] = 'Buscar';
+$lang['logsPrivateChannels'] = 'Canals privats';
+$lang['logsPrivateMessages'] = 'Missatges privats';
+
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/cy.php b/library/ajaxchat/chat/lib/lang/cy.php
new file mode 100644
index 000000000..dea446df5
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/cy.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Alan Davies
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Enw';
+$lang['password'] = 'Cyfrinair';
+$lang['login'] = 'Mewngofnodi';
+$lang['logout'] = 'Allgofnodi';
+$lang['channel'] = 'Sianel';
+$lang['style'] = 'Steil';
+$lang['language'] = 'Iaith';
+$lang['inputLineBreak'] = 'Gwasgwch SHIFT+ENTER i orfodi llinell newydd';
+$lang['messageSubmit'] = 'Anfon';
+$lang['registeredUsers'] = 'Defnyddwyr Cofrestredig';
+$lang['onlineUsers'] = 'Defnyddwyr ar-lein';
+$lang['toggleAutoScroll'] = 'Awtorhôl ymlaen/bant';
+$lang['toggleAudio'] = 'Sain ymlaen/bant';
+$lang['toggleHelp'] = 'Dangos/cuddio cymorth';
+$lang['toggleSettings'] = 'Dangos/cuddio gosodiadau';
+$lang['toggleOnlineList'] = 'Dangos/cuddio rhestr ar-lein';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Dyfyniad';
+$lang['bbCodeLabelCode'] = 'Cod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Delwedd';
+$lang['bbCodeLabelColor'] = 'Lliw Ffont';
+$lang['bbCodeTitleBold'] = 'Testun bras: [b]testun[/b]';
+$lang['bbCodeTitleItalic'] = 'Testun italig: [i]testun[/i]';
+$lang['bbCodeTitleUnderline'] = 'Tanlinellu testun: [u]testun[/u]';
+$lang['bbCodeTitleQuote'] = 'Dyfynnu testun: [quote]testun[/quote] neu [quote=awdur]testun[/quote]';
+$lang['bbCodeTitleCode'] = 'Dangos cod: [code]cod[/code]';
+$lang['bbCodeTitleURL'] = 'Mewnosod URL: [url]http://example.org[/url] neu [url=http://example.org]testun[/url]';
+$lang['bbCodeTitleImg'] = 'Mewnosod delwedd: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Lliw Ffont: [color=red]testun[/color]';
+$lang['help'] = 'Cymorth';
+$lang['helpItemDescJoin'] = 'Ymunwch â sianel:';
+$lang['helpItemCodeJoin'] = '/join EnwSianel';
+$lang['helpItemDescJoinCreate'] = 'Crëwch ystafell breifat (Defnyddwyr cofrestredig yn unig):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Gwahodd rhywun (e.e. i ystafell breifat):';
+$lang['helpItemCodeInvite'] = '/invite Enw';
+$lang['helpItemDescUninvite'] = 'Tynnu gwahaoddiad yn ôl:';
+$lang['helpItemCodeUninvite'] = '/uninvite Enw';
+$lang['helpItemDescLogout'] = 'Allgofnodwch o Sgwrs:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Neges breifat:';
+$lang['helpItemCodePrivateMessage'] = '/msg Testun Enw';
+$lang['helpItemDescQueryOpen'] = 'Agorwch sianel breifat:';
+$lang['helpItemCodeQueryOpen'] = '/query Enw';
+$lang['helpItemDescQueryClose'] = 'Ceuwch sianel breifat:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Disgrifiwch weithred:';
+$lang['helpItemCodeAction'] = '/action Testun';
+$lang['helpItemDescDescribe'] = 'Disgrifiwch weithred mewn neges breifat:';
+$lang['helpItemCodeDescribe'] = '/describe Testun Enw';
+$lang['helpItemDescIgnore'] = 'Anwybyddu/derbyn negeseuon o ddefnyddiwr:';
+$lang['helpItemCodeIgnore'] = '/ignore Enw';
+$lang['helpItemDescIgnoreList'] = 'Rhestr anwybyddion:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Dangos sianel defnyddiwr:';
+$lang['helpItemCodeWhereis'] = '/whereis Enw';
+$lang['helpItemDescKick'] = 'Ciciwch ddefnyddiwr (Cymedrolwyr yn unig):';
+$lang['helpItemCodeKick'] = '/kick Enw [Gwahardd munudau]';
+$lang['helpItemDescUnban'] = 'Dadwahardd defnyddiwr (Cymedrolwyr yn unig):';
+$lang['helpItemCodeUnban'] = '/unban Enw';
+$lang['helpItemDescBans'] = 'Rhestr waharddogion (Cymedrolwyr yn unig):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Dangos IP defnyddiwr (Cymedrolwyr yn unig):';
+$lang['helpItemCodeWhois'] = '/whois Enw';
+$lang['helpItemDescWho'] = 'Rhestr ddefnyddwyr ar-lein:';
+$lang['helpItemCodeWho'] = '/who [EnwSianel]';
+$lang['helpItemDescList'] = 'Rhestr sianeli ar gael:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Rholio dis:';
+$lang['helpItemCodeRoll'] = '/roll [nifer]d[ochrau]'; //posib angen newid hwn
+$lang['helpItemDescNick'] = 'Newid enw:';
+$lang['helpItemCodeNick'] = '/nick Enw';
+$lang['settings'] = 'Gosodiadau';
+$lang['settingsBBCode'] = 'Galluogi BBCode:';
+$lang['settingsBBCodeImages'] = 'Galluogi delweddau BBCode:';
+$lang['settingsBBCodeColors'] = 'Galluogi lliwiau ffont BBCode:';
+$lang['settingsHyperLinks'] = 'Galluogi dolenni:';
+$lang['settingsLineBreaks'] = 'Galluogi toriadau llinell:';
+$lang['settingsEmoticons'] = 'Galluogi gwenogluniau:';
+$lang['settingsAutoFocus'] = 'Gosod y ffocws ar y maes mewnbwn yn awtomatig:';
+$lang['settingsMaxMessages'] = 'Uchafswm y negeseuon yn y rhestr sgwrs:';
+$lang['settingsWordWrap'] = 'Galluogi lapio geiriau hir:';
+$lang['settingsMaxWordLength'] = 'Hyd mwyaf y gair cyn iddo gael ei lapio:';
+$lang['settingsDateFormat'] = 'Fformat y dyddiad a\'r amser:';
+$lang['settingsPersistFontColor'] = 'Lliw ffont parhaus:';
+$lang['settingsAudioVolume'] = 'Uchder Sain:';
+$lang['settingsSoundReceive'] = 'Sain am negeseuon yn dyfod i mewn:';
+$lang['settingsSoundSend'] = 'Sain am negeseuon yn mynd allan:';
+$lang['settingsSoundEnter'] = 'Sain am fewngofnodi a negeseuon myned i sianeli:';
+$lang['settingsSoundLeave'] = 'Sain am allgofnodi a negeseuon gadael sianeli:';
+$lang['settingsSoundChatBot'] = 'Sain am negeseuon sgwrsbot:';
+$lang['settingsSoundError'] = 'Sain am wallnegeseuon:';
+$lang['settingsBlink'] = 'Fflachio teitl y ffenestr ar negeseuon newydd:';
+$lang['settingsBlinkInterval'] = 'Cyfwng fflachio mewn milieiliadau:';
+$lang['settingsBlinkIntervalNumber'] = 'Nifer y cyfyngau fflachio:';
+$lang['playSelectedSound'] = 'Chwarae\'r sain hon';
+$lang['requiresJavaScript'] = 'Mae angen JavaScript ar gyfer y Sgwrs hon.';
+$lang['errorInvalidUser'] = 'Enw annilys.';
+$lang['errorUserInUse'] = 'Enw\'n bodoli eisoes.';
+$lang['errorBanned'] = 'Gwaharddwyd y Defnyddiwr neu\'r IP.';
+$lang['errorMaxUsersLoggedIn'] = 'Mae\'r sgwrs wedi cyrraedd yr uchafswm o ddefnyddwyr.';
+$lang['errorChatClosed'] = 'Mae\'r sgwrs ar gau yn bresennol.';
+$lang['logsTitle'] = 'Sgwrs AJAX - Logiau';
+$lang['logsDate'] = 'Dyddiad';
+$lang['logsTime'] = 'Amser';
+$lang['logsSearch'] = 'Chwilio';
+$lang['logsPrivateChannels'] = 'Sianeli Preifat';
+$lang['logsPrivateMessages'] = 'Negeseuon Preifat';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/cz.php b/library/ajaxchat/chat/lib/lang/cz.php
new file mode 100644
index 000000000..cc6868c1e
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/cz.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Jméno uživatele';
+$lang['password'] = 'Heslo';
+$lang['login'] = 'Přihlásit';
+$lang['logout'] = 'Odhlásit';
+$lang['channel'] = 'Místnost';
+$lang['style'] = 'Styl';
+$lang['language'] = 'Jazyk';
+$lang['inputLineBreak'] = 'Pro zalomení řádku stiskni SHIFT+ENTER';
+$lang['messageSubmit'] = 'Odeslat';
+$lang['registeredUsers'] = 'Registrovaní uživatelé';
+$lang['onlineUsers'] = 'Přihlášení uživatelé';
+$lang['toggleAutoScroll'] = 'Posouvání textu zapnuto/vypnuto';
+$lang['toggleAudio'] = 'Zvuk zapnutý/vypnutý';
+$lang['toggleHelp'] = 'Zobrazit/skrýt nápovědu';
+$lang['toggleSettings'] = 'Zobrazit/skrýt nastavení';
+$lang['toggleOnlineList'] = 'Zobrazit/skrýt seznam přihlášených';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citace';
+$lang['bbCodeLabelCode'] = 'Kód';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Obrázek';
+$lang['bbCodeLabelColor'] = 'Barva písma';
+$lang['bbCodeTitleBold'] = 'Tučně: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Kurzívou: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podtržené: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citace: [quote]text[/quote] nebo [quote=autor]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Zobrazit kód: [code]kód[/code]';
+$lang['bbCodeTitleURL'] = 'Vložit URL: [url]http://example.org[/url] nebo [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Vložit obrázek: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Barva písma: [color=red]text[/color]';
+$lang['help'] = 'Nápověda';
+$lang['helpItemDescJoin'] = 'Vstup do místnosti:';
+$lang['helpItemCodeJoin'] = '/join Místnost';
+$lang['helpItemDescJoinCreate'] = 'Vytvořit vlastní místnost (Pouze registrovaní uživatelé):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Pozvání k soukromému rozhovoru (např. do vlastní místnosti):';
+$lang['helpItemCodeInvite'] = '/invite Uživatel';
+$lang['helpItemDescUninvite'] = 'Odvolat pozvání:';
+$lang['helpItemCodeUninvite'] = '/uninvite Uživatel';
+$lang['helpItemDescLogout'] = 'Odhlášení z chatu:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Soukromá zpráva:';
+$lang['helpItemCodePrivateMessage'] = '/msg Uživatel zpráva';
+$lang['helpItemDescQueryOpen'] = 'Soukromý rozhovor:';
+$lang['helpItemCodeQueryOpen'] = '/query Uživatel';
+$lang['helpItemDescQueryClose'] = 'Ukončit soukromý rozhovor:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Co zrovna dělám:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'To samé soukromě:';
+$lang['helpItemCodeDescribe'] = '/describe Uživatel Text';
+$lang['helpItemDescIgnore'] = 'Odmítnout/přijmout zprávu od uživatele:';
+$lang['helpItemCodeIgnore'] = '/ignore (accept) Uživatel';
+$lang['helpItemDescIgnoreList'] = 'Výpis odmítnutých uživatelů:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Najít uživatele:';
+$lang['helpItemCodeWhereis'] = '/whereis Uživatel';
+$lang['helpItemDescKick'] = 'Vyhodit uživatele (Pouze moderátoři):';
+$lang['helpItemCodeKick'] = '/kick Uživatel [Čas v minutách]';
+$lang['helpItemDescUnban'] = 'Omilostnit vyhozeného (Pouze moderátoři):';
+$lang['helpItemCodeUnban'] = '/unban Uživatel';
+$lang['helpItemDescBans'] = 'Výpis vyhozených uživatelů (Pouze moderátoři):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Zobrazit IP uživatele (Pouze moderátoři):';
+$lang['helpItemCodeWhois'] = '/whois Username';
+$lang['helpItemDescWho'] = 'Seznam přihlášených uživatelů:';
+$lang['helpItemCodeWho'] = '/who [Místnost]';
+$lang['helpItemDescList'] = 'Výpis místností:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Hodit kostkou:';
+$lang['helpItemCodeRoll'] = '/roll [číslo]d[počet stran]';
+$lang['helpItemDescNick'] = 'Změnit jméno uživatele:';
+$lang['helpItemCodeNick'] = '/nick Uživatel';
+$lang['settings'] = 'Nastavení';
+$lang['settingsBBCode'] = 'Povolit kódy BBCode:';
+$lang['settingsBBCodeImages'] = 'Povolit image BBCode:';
+$lang['settingsBBCodeColors'] = 'Povolit font color BBCode:';
+$lang['settingsHyperLinks'] = 'Povolit odkazy:';
+$lang['settingsLineBreaks'] = 'Povolit více řádků:';
+$lang['settingsEmoticons'] = 'Povolit smajlíky:';
+$lang['settingsAutoFocus'] = 'Automaticky nastavit kurzor na vstupní pole:';
+$lang['settingsMaxMessages'] = 'Maximální počet zpráv v hlavním okně:';
+$lang['settingsWordWrap'] = 'Povolit zalomení řádku u dlouhého slova:';
+$lang['settingsMaxWordLength'] = 'Maximální délka slova, než bude zalomeno:';
+$lang['settingsDateFormat'] = 'Formát zobrazení data a času:';
+$lang['settingsPersistFontColor'] = 'Neměnná barva textu:';
+$lang['settingsAudioVolume'] = 'Hlasitost:';
+$lang['settingsSoundReceive'] = 'Zvuk pro příchozí zprávy:';
+$lang['settingsSoundSend'] = 'Zvuk pro odchozí zprávy:';
+$lang['settingsSoundEnter'] = 'Zvuk při přihlášení nebo vstupu do místnosti:';
+$lang['settingsSoundLeave'] = 'Zvuk při odhlášení nebo odchodu z místnosti:';
+$lang['settingsSoundChatBot'] = 'Zvuk při zprávě chatbota:';
+$lang['settingsSoundError'] = 'Zvuk při chybové zprávě:';
+$lang['settingsBlink'] = 'Blikání titulku okna při příchozí zprávě:';
+$lang['settingsBlinkInterval'] = 'Interval blikání v milisekundách:';
+$lang['settingsBlinkIntervalNumber'] = 'Počet bliknutí:';
+$lang['playSelectedSound'] = 'Přehrát vybraný zvuk:';
+$lang['requiresJavaScript'] = 'Pro tento chat musíš mít zapnutý JavaScript.';
+$lang['errorInvalidUser'] = 'Uživatel neexistuje.';
+$lang['errorUserInUse'] = 'To jméno už je používáno.';
+$lang['errorBanned'] = 'Uživatel nebo IP adresa jsou na seznamu vyhozených.';
+$lang['errorMaxUsersLoggedIn'] = 'Chat je plný.';
+$lang['errorChatClosed'] = 'Chat je v tuto chvíli mimo provoz.';
+$lang['logsTitle'] = 'AJAX Chat - Logy';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Čas';
+$lang['logsSearch'] = 'Hledej';
+$lang['logsPrivateChannels'] = 'Soukromé místnosti';
+$lang['logsPrivateMessages'] = 'Soukromé zprávy';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/da.php b/library/ajaxchat/chat/lib/lang/da.php
new file mode 100644
index 000000000..55e7eff1b
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/da.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Brugernavn';
+$lang['password'] = 'Adgangskode';
+$lang['login'] = 'Log ind';
+$lang['logout'] = 'Log ud';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Sprog';
+$lang['inputLineBreak'] = 'Tryk SHIFT+ENTER For at lave et linjeskift';
+$lang['messageSubmit'] = 'Send';
+$lang['registeredUsers'] = 'Registrerede brugere';
+$lang['onlineUsers'] = 'Online brugere';
+$lang['toggleAutoScroll'] = 'Autoscroll til/fra';
+$lang['toggleAudio'] = 'Lyd til/fra';
+$lang['toggleHelp'] = 'Vis/skjul Hjælp';
+$lang['toggleSettings'] = 'Vis/skjul indstillinger';
+$lang['toggleOnlineList'] = 'Vis/Skjul online liste';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citat';
+$lang['bbCodeLabelCode'] = 'Kode';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Billede';
+$lang['bbCodeLabelColor'] = 'Font Farve';
+$lang['bbCodeTitleBold'] = 'Fed tekst: [b]tekstt[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursiv tekst: [i]tekst[/i]';
+$lang['bbCodeTitleUnderline'] = 'Understreget tekst: [u]tekst[/u]';
+$lang['bbCodeTitleQuote'] = 'Citer tekst: [quote]citat[/quote] eller [quote=author]tekst[/quote]';
+$lang['bbCodeTitleCode'] = 'Vis kode: [code]kode[/code]';
+$lang['bbCodeTitleURL'] = 'Indsæt URL: [url]http://example.org[/url] eller [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Indsæt image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Font Farve: [color=red]tekst[/color]';
+$lang['help'] = 'Hjælp';
+$lang['helpItemDescJoin'] = 'Deltag i en kanal:';
+$lang['helpItemCodeJoin'] = '/join Kanalnavn';
+$lang['helpItemDescJoinCreate'] = 'Opret et rum (kun for registrerede brugere):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Inviter person (fx til et privat rum):';
+$lang['helpItemCodeInvite'] = '/invite brugernavn';
+$lang['helpItemDescUninvite'] = 'Anuller invitation:';
+$lang['helpItemCodeUninvite'] = '/uninvite brugernavn';
+$lang['helpItemDescLogout'] = 'Log ud af chatten:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privat besked:';
+$lang['helpItemCodePrivateMessage'] = '/msg brugernavn Tekst';
+$lang['helpItemDescQueryOpen'] = 'Åben en privat kanal:';
+$lang['helpItemCodeQueryOpen'] = '/query brugernavn';
+$lang['helpItemDescQueryClose'] = 'Luk en privat kanal:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'beskrivende handling:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Beskrivende handling i privat besked:';
+$lang['helpItemCodeDescribe'] = '/describe brugernavn Tekst';
+$lang['helpItemDescIgnore'] = 'Ignorer/accepter beskeder fra bruger:';
+$lang['helpItemCodeIgnore'] = '/ignore brugernavn';
+$lang['helpItemDescIgnoreList'] = 'Vis ignorerede brugere:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Vis bruger kanal:';
+$lang['helpItemCodeWhereis'] = '/whereis brugernavn';
+$lang['helpItemDescKick'] = 'Spark en bruger ud af chatten (Moderators):';
+$lang['helpItemCodeKick'] = '/kick brugernavn [Minuter banlyst]';
+$lang['helpItemDescUnban'] = 'fjern banlysning af bruger (Moderators):';
+$lang['helpItemCodeUnban'] = '/unban brugernavn';
+$lang['helpItemDescBans'] = 'Vis banlyste brugere (Moderators):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Vis en brugers IP (Moderators):';
+$lang['helpItemCodeWhois'] = '/whois brugernavn';
+$lang['helpItemDescWho'] = 'Vis online brugere:';
+$lang['helpItemCodeWho'] = '/who [kanalnavn]';
+$lang['helpItemDescList'] = 'Vis tilgængelige kanaler:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'kast terninger:';
+$lang['helpItemCodeRoll'] = '/roll [antal]d[sider]';
+$lang['helpItemDescNick'] = 'Skift brugernavn:';
+$lang['helpItemCodeNick'] = '/nick brugernavn';
+$lang['settings'] = 'Indstillinger';
+$lang['settingsBBCode'] = 'Aktiver BBCode:';
+$lang['settingsBBCodeImages'] = 'Aktiver billede BBCode:';
+$lang['settingsBBCodeColors'] = 'Aktiver font farve BBCode:';
+$lang['settingsHyperLinks'] = 'Aktiver hyperlinks:';
+$lang['settingsLineBreaks'] = 'Aktiver linjeskift:';
+$lang['settingsEmoticons'] = 'Aktiver smileys:';
+$lang['settingsAutoFocus'] = 'Automatisk indstild fokus på indtastningsfeltet:';
+$lang['settingsMaxMessages'] = 'Maximum antal beskeder i chat list:';
+$lang['settingsWordWrap'] = 'Aktiver ombrydning af lange ord:';
+$lang['settingsMaxWordLength'] = 'Maximum længde af et ord før det bliver ombrudt:';
+$lang['settingsDateFormat'] = 'Metoden hvorpå data og klokkeslet vises:';
+$lang['settingsPersistFontColor'] = 'Vedhold en tekst farve:';
+$lang['settingsAudioVolume'] = 'Lydstyrke:';
+$lang['settingsSoundReceive'] = 'Lyd for indgående beskeder:';
+$lang['settingsSoundSend'] = 'Lyd for udgående:';
+$lang['settingsSoundEnter'] = 'Lyd ved login og kanal beskeder:';
+$lang['settingsSoundLeave'] = 'Lyd ved login og forlad kanal beskeder:';
+$lang['settingsSoundChatBot'] = 'Lyd ved ChatBot beskeder:';
+$lang['settingsSoundError'] = 'Lyd ved fejlmeddelse:';
+$lang['settingsBlink'] = 'Blink vindue titel ved nye beskeder:';
+$lang['settingsBlinkInterval'] = 'Blink interval i millisekonder:';
+$lang['settingsBlinkIntervalNumber'] = 'Antal blink intervaler:';
+$lang['playSelectedSound'] = 'Afspil valgte lyd';
+$lang['requiresJavaScript'] = 'JavaScript er nødvændigt for at kunne bruge denne chat.';
+$lang['errorInvalidUser'] = 'Ugyldigt brugernavn.';
+$lang['errorUserInUse'] = 'Brugernavn allerede i brug.';
+$lang['errorBanned'] = 'Bruger eller IP er blevet banned.';
+$lang['errorMaxUsersLoggedIn'] = 'Chatten har opnået det maksimale antal online brugere.';
+$lang['errorChatClosed'] = 'Chatten er pt lukket.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Dato';
+$lang['logsTime'] = 'Tid';
+$lang['logsSearch'] = 'Søg';
+$lang['logsPrivateChannels'] = 'Private Kanaler';
+$lang['logsPrivateMessages'] = 'Private Beskeder';
+?>
diff --git a/library/ajaxchat/chat/lib/lang/de.php b/library/ajaxchat/chat/lib/lang/de.php
new file mode 100644
index 000000000..f345d100a
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/de.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Benutzername';
+$lang['password'] = 'Passwort';
+$lang['login'] = 'Login';
+$lang['logout'] = 'Logout';
+$lang['channel'] = 'Raum';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Sprache';
+$lang['inputLineBreak'] = 'UMSCHALT+EINGABE drücken um einen Zeilenumbruch zu erzeugen';
+$lang['messageSubmit'] = 'Abschicken';
+$lang['registeredUsers'] = 'Registrierte Benutzer';
+$lang['onlineUsers'] = 'Online Benutzer';
+$lang['toggleAutoScroll'] = 'Autoscroll an/aus';
+$lang['toggleAudio'] = 'Sound an/aus';
+$lang['toggleHelp'] = 'Hilfe anzeigen/verstecken';
+$lang['toggleSettings'] = 'Einstellungen anzeigen/verstecken';
+$lang['toggleOnlineList'] = 'Online Benutzer anzeigen/verstecken';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Zitat';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Bild';
+$lang['bbCodeLabelColor'] = 'Schriftfarbe';
+$lang['bbCodeTitleBold'] = 'Fett: [b]Text[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursiv: [i]Text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Unterstrichen: [u]Text[/u]';
+$lang['bbCodeTitleQuote'] = 'Zitat: [quote]Text[/quote] oder [quote=Autor]Text[/quote]';
+$lang['bbCodeTitleCode'] = 'Code anzeigen: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Link einfügen: [url]http://example.org[/url] oder [url=http://example.org]Text[/url]';
+$lang['bbCodeTitleImg'] = 'Bild einfügen: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Schriftfarbe: [color=red]Text[/color]';
+$lang['help'] = 'Hilfe';
+$lang['helpItemDescJoin'] = 'Raum betreten:';
+$lang['helpItemCodeJoin'] = '/join Raumname';
+$lang['helpItemDescJoinCreate'] = 'Einen privaten Raum erstellen (nur registrierte Benutzer):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Jemanden einladen (z.B. in einen privaten Raum):';
+$lang['helpItemCodeInvite'] = '/invite Benutzername';
+$lang['helpItemDescUninvite'] = 'Einladung zurücknehmen:';
+$lang['helpItemCodeUninvite'] = '/uninvite Benutzername';
+$lang['helpItemDescLogout'] = 'Logout aus dem Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Private Nachricht:';
+$lang['helpItemCodePrivateMessage'] = '/msg Benutzername Text';
+$lang['helpItemDescQueryOpen'] = 'Privaten Kanal öffnen:';
+$lang['helpItemCodeQueryOpen'] = '/query Benutzername';
+$lang['helpItemDescQueryClose'] = 'Privaten Kanal schließen:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Aktion beschreiben:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'Aktion in privater Nachricht beschreiben:';
+$lang['helpItemCodeDescribe'] = '/describe Benutzername Text';
+$lang['helpItemDescIgnore'] = 'Nachrichten von Benutzer ignorieren/akzeptieren:';
+$lang['helpItemCodeIgnore'] = '/ignore Benutzername';
+$lang['helpItemDescIgnoreList'] = 'Ignorierte Benutzer auflisten:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Raum eines Benutzers anzeigen:';
+$lang['helpItemCodeWhereis'] = '/whereis Benutzername';
+$lang['helpItemDescKick'] = 'Benutzer ausschließen (nur Moderatoren):';
+$lang['helpItemCodeKick'] = '/kick Benutzername [Ausschluss in Minuten]';
+$lang['helpItemDescUnban'] = 'Ausschluss eines Benutzers aufheben (nur Moderatoren):';
+$lang['helpItemCodeUnban'] = '/unban Benutzername';
+$lang['helpItemDescBans'] = 'Ausgeschlossene Benutzer auflisten (nur Moderatoren):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Benutzer IP anzeigen (nur Moderatoren):';
+$lang['helpItemCodeWhois'] = '/whois Benutzername';
+$lang['helpItemDescWho'] = 'Online Benutzer auflisten:';
+$lang['helpItemCodeWho'] = '/who [Kanalname]';
+$lang['helpItemDescList'] = 'Verfügbare Räume auflisten:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Würfeln:';
+$lang['helpItemCodeRoll'] = '/roll [Anzahl]d[Seiten]';
+$lang['helpItemDescNick'] = 'Benutzernamen ändern:';
+$lang['helpItemCodeNick'] = '/nick Benutzername';
+$lang['settings'] = 'Einstellungen';
+$lang['settingsBBCode'] = 'BBCode aktivieren:';
+$lang['settingsBBCodeImages'] = ' Bilder BBCode aktivieren:';
+$lang['settingsBBCodeColors'] = 'Schriftfarben BBCode aktivieren:';
+$lang['settingsHyperLinks'] = 'Hyperlinks aktivieren:';
+$lang['settingsLineBreaks'] = 'Zeilenumbrüche aktivieren:';
+$lang['settingsEmoticons'] = 'Smileys aktivieren:';
+$lang['settingsAutoFocus'] = 'Automatisch den Fokus auf das Eingabefeld setzen:';
+$lang['settingsMaxMessages'] = 'Maximale Anzahl der Nachrichten in der Chatliste:';
+$lang['settingsWordWrap'] = 'Lange Wörter umbrechen:';
+$lang['settingsMaxWordLength'] = 'Maximallänge eines Wortes bevor es umgebrochen wird:';
+$lang['settingsDateFormat'] = 'Datums- und Zeitanzeige:';
+$lang['settingsPersistFontColor'] = 'Schriftfarbe dauerhaft setzen:';
+$lang['settingsAudioVolume'] = 'Lautstärke:';
+$lang['settingsSoundReceive'] = 'Klang für empfangene Nachrichten:';
+$lang['settingsSoundSend'] = 'Klang für gesendete Nachrichten:';
+$lang['settingsSoundEnter'] = 'Klang für Logins und das Betreten von Räumen:';
+$lang['settingsSoundLeave'] = 'Klang für Logouts und das Verlassen von Räumen:';
+$lang['settingsSoundChatBot'] = 'Klang für Chatbot Nachrichten:';
+$lang['settingsSoundError'] = 'Klang für Fehlermeldungen:';
+$lang['settingsBlink'] = 'Blinkender Fenstertitel bei neuen Nachrichten:';
+$lang['settingsBlinkInterval'] = 'Blink-Intervall in Millisekunden:';
+$lang['settingsBlinkIntervalNumber'] = 'Anzahl der Blink-Intervalle:';
+$lang['playSelectedSound'] = 'Ausgewählten Klang abspielen';
+$lang['requiresJavaScript'] = 'JavaScript wird für diesen Chat benötigt.';
+$lang['errorInvalidUser'] = 'Ungültiger Benutzername.';
+$lang['errorUserInUse'] = 'Benutzername in Verwendung.';
+$lang['errorBanned'] = 'Benutzer oder IP ist ausgeschlossen.';
+$lang['errorMaxUsersLoggedIn'] = 'Der Chat hat die maximale Anzahl eingeloggter Benutzer erreicht.';
+$lang['errorChatClosed'] = 'Der Chat ist zur Zeit geschlossen.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Uhrzeit';
+$lang['logsSearch'] = 'Suche';
+$lang['logsPrivateChannels'] = 'Private Räume';
+$lang['logsPrivateMessages'] = 'Private Nachrichten';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/el.php b/library/ajaxchat/chat/lib/lang/el.php
new file mode 100644
index 000000000..526c31bf9
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/el.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author panas
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Όνομα χρήστη';
+$lang['password'] = 'Κωδικός';
+$lang['login'] = 'Σύνδεση';
+$lang['logout'] = 'Αποσύνδεση';
+$lang['channel'] = 'Κανάλι';
+$lang['style'] = 'Στυλ';
+$lang['language'] = 'Γλώσσα';
+$lang['inputLineBreak'] = 'Πατήστε SHIFT+ENTER για να εισάγετε μια νέα γραμμή';
+$lang['messageSubmit'] = 'Υποβολή';
+$lang['registeredUsers'] = 'Εγγεγραμμένοι χρήστες';
+$lang['onlineUsers'] = 'Συνδεδεμένοι χρήστες';
+$lang['toggleAutoScroll'] = 'Αυτόματη κύλιση ναι/όχι';
+$lang['toggleAudio'] = 'Ήχος ναι/όχι';
+$lang['toggleHelp'] = 'Εμφάνιση/απόκρυψη βοήθειας';
+$lang['toggleSettings'] = 'Εμφάνιση/απόκρυψη ρυθμίσεων';
+$lang['toggleOnlineList'] = 'Εμφάνιση/απόκρυψη λίστας συνδεδεμένων';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Παράθεση';
+$lang['bbCodeLabelCode'] = 'Κώδικας';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Χρώμα γραμματοσειράς';
+$lang['bbCodeTitleBold'] = 'Έντονο κείμενο: [b]κείμενο[/b]';
+$lang['bbCodeTitleItalic'] = 'Πλάγια γραφή: [i]κείμενο[/i]';
+$lang['bbCodeTitleUnderline'] = 'Υπογραμμισμένο κείμενο: [u]κείμενο[/u]';
+$lang['bbCodeTitleQuote'] = 'Κείμενο σε παράθεση: [quote]κείμενο[/quote] ή [quote=author]κείμενο[/quote]';
+$lang['bbCodeTitleCode'] = 'Εμφάνιση κώδικα: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Εισαγωγή URL: [url]http://example.org[/url] ή [url=http://example.org]κείμενο[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Χρώμα γραμματοσειράς: [color=red]κείμενο[/color]';
+$lang['help'] = 'Βοήθεια';
+$lang['helpItemDescJoin'] = 'Είσοδος σε ένα κανάλι:';
+$lang['helpItemCodeJoin'] = '/join όνομα_καναλιού';
+$lang['helpItemDescJoinCreate'] = 'Δημιουργία πριβέ καναλιού(μόνο για εγγεγραμμένους):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Για να προκαλέσετε (π.χ. σε ένα πριβέ κανάλι):';
+$lang['helpItemCodeInvite'] = '/invite όνομα';
+$lang['helpItemDescUninvite'] = 'Ακύρωση πρόσκλησης:';
+$lang['helpItemCodeUninvite'] = '/uninvite όνομα';
+$lang['helpItemDescLogout'] = 'Αποσύνδεση από το Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Προσωπικό μήνυμα:';
+$lang['helpItemCodePrivateMessage'] = '/msg όνομα_χρήστη κείμενο';
+$lang['helpItemDescQueryOpen'] = 'Άνοιγμα πριβέ καναλιού:';
+$lang['helpItemCodeQueryOpen'] = '/query όνομα χρήστη';
+$lang['helpItemDescQueryClose'] = 'Κλεισιμό ενώς πριβέ καναλιού:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Περιγραφή ενέργειας:';
+$lang['helpItemCodeAction'] = '/action κείμενο';
+$lang['helpItemDescDescribe'] = 'Περιγραφή ενέργειας με προσωπικό μήνυμα:';
+$lang['helpItemCodeDescribe'] = '/describe όνομα_χρήστη κείμενο';
+$lang['helpItemDescIgnore'] = 'Αγνόηση/αποδοχή μηνυμάτων από χρήστη:';
+$lang['helpItemCodeIgnore'] = '/ignore όνομα_χρήστη';
+$lang['helpItemDescIgnoreList'] = 'Εμφάνιση λίστας αγνοημένων:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Εμφάνιση καναλιού χρήστη:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Kick έναν χρήστη (Μόνον για συντονιστές):';
+$lang['helpItemCodeKick'] = '/kick όνομα χρήστη [λεπτά αποκλεισμού]';
+$lang['helpItemDescUnban'] = 'Αφαίρεση αποκλεισμού από χρήστη (Μόνον για συντονιστές):';
+$lang['helpItemCodeUnban'] = '/unban όνομα_χρήστη';
+$lang['helpItemDescBans'] = 'Λίστα αποκλεισμένων χρηστών (Μόνον για συντονιστές):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Εμφανίζει την IP του χρήστη (Μόνον για συντονιστές):';
+$lang['helpItemCodeWhois'] = '/whois όνομα χρήστη';
+$lang['helpItemDescWho'] = 'Λίστα συνδεδεμένων χρηστών:';
+$lang['helpItemCodeWho'] = '/who [όνομακαναλιού]';
+$lang['helpItemDescList'] = 'Εμφάνιση διαθέσιμων καναλιών:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Κύλιση ζαριών:';
+$lang['helpItemCodeRoll'] = '/roll [αριθμός]d[πλευρές]';
+$lang['helpItemDescNick'] = 'Αλλαγή ονόματος:';
+$lang['helpItemCodeNick'] = '/nick όνομα_χρήστη';
+$lang['settings'] = 'Ρυθμίσεις';
+$lang['settingsBBCode'] = 'Ενεργοποίηση BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Ενεργοποίηση συνδέσμων:';
+$lang['settingsLineBreaks'] = 'Ενεργοποίηση αλλαγής γραμμής:';
+$lang['settingsEmoticons'] = 'Ενεργοποίηση εικονιδίων:';
+$lang['settingsAutoFocus'] = 'Θέστε αυτόματα την εστίαση στο πεδίο εισαγωγής:';
+$lang['settingsMaxMessages'] = 'Μέγιστος αριθμός μηνυμάτων στην λίστα του chat:';
+$lang['settingsWordWrap'] = 'Ενεργοποίηση καλύμματος μεγάλων λέξεων:';
+$lang['settingsMaxWordLength'] = 'Μέγιστο μήκος μιας λέξης χωρίς κάλυμμα:';
+$lang['settingsDateFormat'] = 'Μορφή ημερομηνίας και ώρας που θα εμφανίζετε:';
+$lang['settingsPersistFontColor'] = 'Έντονο χρώμα γραμματοσειράς:';
+$lang['settingsAudioVolume'] = 'Ένταση ήχου:';
+$lang['settingsSoundReceive'] = 'Ήχος για εισερχόμενα μηνύματα:';
+$lang['settingsSoundSend'] = 'Ήχος για εξερχόμενα μηνύματα:';
+$lang['settingsSoundEnter'] = 'Ήχος για μηνύματα σύνδεσης και εισόδου:';
+$lang['settingsSoundLeave'] = 'Ήχος για μηνύματα αποχώρισης και αποσύνδεσης:';
+$lang['settingsSoundChatBot'] = 'Ήχος για μηνύματα του chatbot:';
+$lang['settingsSoundError'] = 'Ήχος για μηνύματα λάθους:';
+$lang['settingsBlink'] = 'Αναβόσβημα τίτλου σε νέα μηνύματα:';
+$lang['settingsBlinkInterval'] = 'Ρυθμός αναβοσβήματος σε χιλιοστά του δευτερόλεπτου:';
+$lang['settingsBlinkIntervalNumber'] = 'Αριθμός αναβοσβήματος οθόνης:';
+$lang['playSelectedSound'] = 'Αναπαραγωγή επιλεγμένου ήχου';
+$lang['requiresJavaScript'] = 'Χρειάζεται JavaScript για το Chat.';
+$lang['errorInvalidUser'] = 'Ακατάλληλο όνομα χρήστη.';
+$lang['errorUserInUse'] = 'Το όνομα υπάρχει ήδη.';
+$lang['errorBanned'] = 'Το όνομα χρήστη ή IP είναι αποκλεισμένα.';
+$lang['errorMaxUsersLoggedIn'] = 'Το chat έχει φτάσει το μέγιστο αριθμό χρηστών.';
+$lang['errorChatClosed'] = 'Το chat είναι κλειστό προς το παρόν.';
+$lang['logsTitle'] = 'AJAX Chat - Καταγραφές';
+$lang['logsDate'] = 'Ημερομηνία';
+$lang['logsTime'] = 'Ώρα';
+$lang['logsSearch'] = 'Αναζήτηση';
+$lang['logsPrivateChannels'] = 'Πριβέ κανάλια';
+$lang['logsPrivateMessages'] = 'προσωπικά μηνύματα';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/en.php b/library/ajaxchat/chat/lib/lang/en.php
new file mode 100644
index 000000000..cb9492bde
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/en.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Username';
+$lang['password'] = 'Password';
+$lang['login'] = 'Login';
+$lang['logout'] = 'Logout';
+$lang['channel'] = 'Channel';
+$lang['style'] = 'Style';
+$lang['language'] = 'Language';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'Submit';
+$lang['registeredUsers'] = 'Registered Users';
+$lang['onlineUsers'] = 'Online users';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Quote';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Font Color';
+$lang['bbCodeTitleBold'] = 'Bold text: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Italic text: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Underline text: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Quote text: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Code display: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Insert URL: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Font Color: [color=red]text[/color]';
+$lang['help'] = 'Help';
+$lang['helpItemDescJoin'] = 'Join a channel:';
+$lang['helpItemCodeJoin'] = '/join Channelname';
+$lang['helpItemDescJoinCreate'] = 'Create a private room (Registered users only):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Invite someone (e.g. to a private room):';
+$lang['helpItemCodeInvite'] = '/invite Username';
+$lang['helpItemDescUninvite'] = 'Revoke invitation:';
+$lang['helpItemCodeUninvite'] = '/uninvite Username';
+$lang['helpItemDescLogout'] = 'Logout from Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Private message:';
+$lang['helpItemCodePrivateMessage'] = '/msg Username Text';
+$lang['helpItemDescQueryOpen'] = 'Open a private channel:';
+$lang['helpItemCodeQueryOpen'] = '/query Username';
+$lang['helpItemDescQueryClose'] = 'Close a private channel:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Describe action:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'Describe action in private message:';
+$lang['helpItemCodeDescribe'] = '/describe Username Text';
+$lang['helpItemDescIgnore'] = 'Ignore/accept messages from user:';
+$lang['helpItemCodeIgnore'] = '/ignore Username';
+$lang['helpItemDescIgnoreList'] = 'List ignored users:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Kick a user (Moderators only):';
+$lang['helpItemCodeKick'] = '/kick Username [Minutes banned]';
+$lang['helpItemDescUnban'] = 'Unban a user (Moderators only):';
+$lang['helpItemCodeUnban'] = '/unban Username';
+$lang['helpItemDescBans'] = 'List banned users (Moderators only):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Display user IP (Moderators only):';
+$lang['helpItemCodeWhois'] = '/whois Username';
+$lang['helpItemDescWho'] = 'List online users:';
+$lang['helpItemCodeWho'] = '/who [Channelname]';
+$lang['helpItemDescList'] = 'List available channels:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Roll dice:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'JavaScript is required for this Chat.';
+$lang['errorInvalidUser'] = 'Invalid username.';
+$lang['errorUserInUse'] = 'Username in use.';
+$lang['errorBanned'] = 'User or IP is banned.';
+$lang['errorMaxUsersLoggedIn'] = 'The chat has reached the maximum number of logged-in users.';
+$lang['errorChatClosed'] = 'The chat is closed at the moment.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Date';
+$lang['logsTime'] = 'Time';
+$lang['logsSearch'] = 'Search';
+$lang['logsPrivateChannels'] = 'Private Channels';
+$lang['logsPrivateMessages'] = 'Private Messages';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/es.php b/library/ajaxchat/chat/lib/lang/es.php
new file mode 100644
index 000000000..27b9b7273
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/es.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author - Spanis Translation: Manu Quintans / KeScI [www.e-nologia.com]
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Usuario';
+$lang['password'] = 'Contraseña';
+$lang['login'] = 'Conectar';
+$lang['logout'] = 'Desconectar';
+$lang['channel'] = 'Canal';
+$lang['style'] = 'Estilo';
+$lang['language'] = 'Idioma';
+$lang['inputLineBreak'] = 'Pulse SHIFT+ENTER para insertar un salto de línea';
+$lang['messageSubmit'] = 'Enviar';
+$lang['registeredUsers'] = 'Usuarios Registrados';
+$lang['onlineUsers'] = 'Usuarios Conectados';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sonido on/off';
+$lang['toggleHelp'] = 'Mostrar/ocultar ayuda';
+$lang['toggleSettings'] = 'Mostrar/ocultar configuración';
+$lang['toggleOnlineList'] = 'Mostrar/ocultar lista conectados';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citar';
+$lang['bbCodeLabelCode'] = 'Código';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Imagen';
+$lang['bbCodeLabelColor'] = 'Color de Fuente';
+$lang['bbCodeTitleBold'] = 'Texto Negrita: [b]texto[/b]';
+$lang['bbCodeTitleItalic'] = 'Texto Cursiva: [i]texto[/i]';
+$lang['bbCodeTitleUnderline'] = 'Texto Subrayado: [u]texto[/u]';
+$lang['bbCodeTitleQuote'] = 'Texto Citado: [quote]texto[/quote] o [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Mostrar código: [code]código[/code]';
+$lang['bbCodeTitleURL'] = 'Insertar URL: [url]http://example.org[/url] or [url=http://example.org]texto[/url]';
+$lang['bbCodeTitleImg'] = 'Insertar imagen: [img]http://example.org/imagen.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Color de Fuente: [color=red]texto[/color]';
+$lang['help'] = 'Ayuda';
+$lang['helpItemDescJoin'] = 'Entrar en canal:';
+$lang['helpItemCodeJoin'] = '/join nombre del canal';
+$lang['helpItemDescJoinCreate'] = 'Crear un canal privado (Solo usuarios registrados):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Invitar a alguien (por ejemplo a un canal privado):';
+$lang['helpItemCodeInvite'] = '/invite Usuario';
+$lang['helpItemDescUninvite'] = 'Anular invitación:';
+$lang['helpItemCodeUninvite'] = '/uninvite Usuario';
+$lang['helpItemDescLogout'] = 'Cerrar sesión:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Mensaje Privado:';
+$lang['helpItemCodePrivateMessage'] = '/msg Usuario Texto';
+$lang['helpItemDescQueryOpen'] = 'Abrir un privado:';
+$lang['helpItemCodeQueryOpen'] = '/query Usuario';
+$lang['helpItemDescQueryClose'] = 'Cerrar privado:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Describir acción:';
+$lang['helpItemCodeAction'] = '/action Texto';
+$lang['helpItemDescDescribe'] = 'Describir acción en mensaje privado:';
+$lang['helpItemCodeDescribe'] = '/describe Usuario Texto';
+$lang['helpItemDescIgnore'] = 'Ignorar/Aceptar mensajes de usuarios:';
+$lang['helpItemCodeIgnore'] = '/ignore Usuario';
+$lang['helpItemDescIgnoreList'] = 'Mostrar usuarios ignorados:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Mostrar canal del usuario:';
+$lang['helpItemCodeWhereis'] = '/whereis Usuario';
+$lang['helpItemDescKick'] = 'Patear usuario (Solo moderadores):';
+$lang['helpItemCodeKick'] = '/kick Usuario [Minutos baneado]';
+$lang['helpItemDescUnban'] = 'Quitar ban usuario (Solo moderadores):';
+$lang['helpItemCodeUnban'] = '/unban Usuario';
+$lang['helpItemDescBans'] = 'Listar usuarios baneados (Solo moderadores):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Mostrar ips de usuarios (Solo moderadores):';
+$lang['helpItemCodeWhois'] = '/whois Usuario';
+$lang['helpItemDescWho'] = 'Mostrar usuarios conectados:';
+$lang['helpItemCodeWho'] = '/who [Channelname]';
+$lang['helpItemDescList'] = 'Lista de canales disponibles:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Tirar dado:';
+$lang['helpItemCodeRoll'] = '/roll [numero]de[lados]';
+$lang['helpItemDescNick'] = 'Cambiar nombre de usuario:';
+$lang['helpItemCodeNick'] = '/nick Usuario';
+$lang['settings'] = 'Configuración';
+$lang['settingsBBCode'] = 'Permitir BBCode:';
+$lang['settingsBBCodeImages'] = 'Permitir BBCode de imagen:';
+$lang['settingsBBCodeColors'] = 'Permitir BBCode de color de fuente:';
+$lang['settingsHyperLinks'] = 'Permitir enlaces:';
+$lang['settingsLineBreaks'] = 'Permitir saltos de línea:';
+$lang['settingsEmoticons'] = 'Permitir emoticonos:';
+$lang['settingsAutoFocus'] = 'Seleccionar el cuadro de ingreso automáticamente:';
+$lang['settingsMaxMessages'] = 'Máximo número de mensajes en la lista del chat:';
+$lang['settingsWordWrap'] = 'Permitir la separación del las palabras largas:';
+$lang['settingsMaxWordLength'] = 'Máximo tamaño de una palabara antes de que se separe:';
+$lang['settingsDateFormat'] = 'Formato de la fecha y hora a mostrar:';
+$lang['settingsPersistFontColor'] = 'Mantener el color de la fuente:';
+$lang['settingsAudioVolume'] = 'Volumen Sonido:';
+$lang['settingsSoundReceive'] = 'Sonido para mensajes entrantes:';
+$lang['settingsSoundSend'] = 'Sonido para mensajes salientes:';
+$lang['settingsSoundEnter'] = 'Sonido para mensajes de conexión y entradas al canal:';
+$lang['settingsSoundLeave'] = 'Sonido para mensajes de desconexión y salidas del canal:';
+$lang['settingsSoundChatBot'] = 'Sonido para mensajes del Chatbot:';
+$lang['settingsSoundError'] = 'Sonido para mensajes de error:';
+$lang['settingsBlink'] = 'Parpadeo del título de la ventana con nuevos mensajes:';
+$lang['settingsBlinkInterval'] = 'Intervalo de parpadeo en milisegundos:';
+$lang['settingsBlinkIntervalNumber'] = 'Número de intervalos de parpadeo:';
+$lang['playSelectedSound'] = 'Reproducir sonido seleccionado';
+$lang['requiresJavaScript'] = 'Necesita tener activado el Javascript en su navegador..';
+$lang['errorInvalidUser'] = 'Usuario Invalido.';
+$lang['errorUserInUse'] = 'Este nombre de usuario esta siendo utilizado en este momento.';
+$lang['errorBanned'] = 'El Usuario o la IP esta baneada..';
+$lang['errorMaxUsersLoggedIn'] = 'El Chat ha alcanzado el número máximo de usuarios conectados.';
+$lang['errorChatClosed'] = 'El Chat está cerrado en estos momentos.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Fecha';
+$lang['logsTime'] = 'Hora';
+$lang['logsSearch'] = 'Buscar';
+$lang['logsPrivateChannels'] = 'Canales Privados';
+$lang['logsPrivateMessages'] = 'Mensajes Privados';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/et.php b/library/ajaxchat/chat/lib/lang/et.php
new file mode 100644
index 000000000..f1169fe19
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/et.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Kasutajanimi';
+$lang['password'] = 'Parool';
+$lang['login'] = 'Sisene';
+$lang['logout'] = 'Välju';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stiil';
+$lang['language'] = 'Keel';
+$lang['inputLineBreak'] = 'Vajuta SHIFT+ENTER, et sisestada reavahe';
+$lang['messageSubmit'] = 'Sisesta';
+$lang['registeredUsers'] = 'Registreeritud kasutajad';
+$lang['onlineUsers'] = 'Sisse loginud kasutajad';
+$lang['toggleAutoScroll'] = 'Automaatne kerimine sees/väljas';
+$lang['toggleAudio'] = 'Helid sees/väljas';
+$lang['toggleHelp'] = 'Näita/Peida Abi';
+$lang['toggleSettings'] = 'Näita/Peida seaded';
+$lang['toggleOnlineList'] = 'Näita/Peida sisse loginuid';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Tsitaat';
+$lang['bbCodeLabelCode'] = 'Kood';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Pilt';
+$lang['bbCodeLabelColor'] = 'Fondi värv';
+$lang['bbCodeTitleBold'] = 'Rasvases kirjas tekst: [b]tekst[/b]';
+$lang['bbCodeTitleItalic'] = 'Kaldkirjas tekst: [i]tekst[/i]';
+$lang['bbCodeTitleUnderline'] = 'Underline text: [u]tekst[/u]';
+$lang['bbCodeTitleQuote'] = 'Tsiteeritud tekst: [quote]tekst[/quote] või [quote=autor]tekst[/quote]';
+$lang['bbCodeTitleCode'] = 'Koodi esitamine: [code]kood[/code]';
+$lang['bbCodeTitleURL'] = 'Lisa URL: [url]http://näide.org[/url] või [url=http://näide.org]tekst[/url]';
+$lang['bbCodeTitleImg'] = 'Lisa pilt: [img]http://näide.org/pilt.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Fondi värv: [color=red]tekst[/color]';
+$lang['help'] = 'Abi';
+$lang['helpItemDescJoin'] = 'Liitu kanaliga:';
+$lang['helpItemCodeJoin'] = '/join Kanalinimi';
+$lang['helpItemDescJoinCreate'] = 'Loo privaat-ruum (Vaid registreeritud kasutajad):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Kutsu kedagi (näiteks privaat-ruumi):';
+$lang['helpItemCodeInvite'] = '/invite Kasutajanimi';
+$lang['helpItemDescUninvite'] = 'Tühista kutse:';
+$lang['helpItemCodeUninvite'] = '/uninvite Kasutajanimi';
+$lang['helpItemDescLogout'] = 'Lahku jutukast:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privaat-sõnum:';
+$lang['helpItemCodePrivateMessage'] = '/msg Kasutajanimi Tekst';
+$lang['helpItemDescQueryOpen'] = 'Ava privaat-kanal:';
+$lang['helpItemCodeQueryOpen'] = '/query Kasutajanimi';
+$lang['helpItemDescQueryClose'] = 'Sulge privaat-kanal:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Kirjelda tegevust:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Kirjelda tegevust privaat-sõnumis:';
+$lang['helpItemCodeDescribe'] = '/describe Kasutajanimi Tekst';
+$lang['helpItemDescIgnore'] = 'Ignoreeri/Tunnusta sõnumeid kindlalt kasutajalt:';
+$lang['helpItemCodeIgnore'] = '/ignore Kasutajanimi';
+$lang['helpItemDescIgnoreList'] = 'Ignoreeritud kasutajate nimekiri:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Mis kanalis asub kasutaja?:';
+$lang['helpItemCodeWhereis'] = '/whereis Kasutajanimi';
+$lang['helpItemDescKick'] = 'Viska kasutaja välja (Ainult moderaatorid):';
+$lang['helpItemCodeKick'] = '/kick Kasutajanimi [minutite hulk mustas nimekirjas]';
+$lang['helpItemDescUnban'] = 'Eemalda kasutaja mustast nimekirjast (Ainult moderaatorid):';
+$lang['helpItemCodeUnban'] = '/unban Kasutajanimi';
+$lang['helpItemDescBans'] = 'Must nimekiri (Ainult moderaatorid):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Näita kasutaja IP aadressit (Ainult moderaatorid):';
+$lang['helpItemCodeWhois'] = '/whois Kasutajanimi';
+$lang['helpItemDescWho'] = 'Jutukasse sisenenud kasutajad:';
+$lang['helpItemCodeWho'] = '/who [Kanalinimi]';
+$lang['helpItemDescList'] = 'Vabade kanalite nimekiri:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Veereta täringut:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[küljed]';
+$lang['helpItemDescNick'] = 'Muuda kasutajanimi:';
+$lang['helpItemCodeNick'] = '/nick Kasutajanimi';
+$lang['settings'] = 'Seaded';
+$lang['settingsBBCode'] = 'Luba BBCode:';
+$lang['settingsBBCodeImages'] = 'Luba pildi BBCode:';
+$lang['settingsBBCodeColors'] = 'Luba fondi värvi BBCode:';
+$lang['settingsHyperLinks'] = 'Luba hüpperlingid:';
+$lang['settingsLineBreaks'] = 'Luba reavahed:';
+$lang['settingsEmoticons'] = 'Luba emotikonid:';
+$lang['settingsAutoFocus'] = 'Sea fookus automaatselt sisestusväljale:';
+$lang['settingsMaxMessages'] = 'Maksimum sõnumite hulk ühes nimekirjas:';
+$lang['settingsWordWrap'] = 'Luba pikkade sõnade murdmine:';
+$lang['settingsMaxWordLength'] = 'Maksimum sõna pikkus enne kui seda murtakse:';
+$lang['settingsDateFormat'] = 'Kuupäeva ja kellaaja formaat:';
+$lang['settingsPersistFontColor'] = 'Püsiv fondi värv';
+$lang['settingsAudioVolume'] = 'Heli tugevus:';
+$lang['settingsSoundReceive'] = 'Heli sisenemisel:';
+$lang['settingsSoundSend'] = 'Heli väljumisel:';
+$lang['settingsSoundEnter'] = 'Heli sisenemisel ja kanalisse sisenemise sõnumitel:';
+$lang['settingsSoundLeave'] = 'Heli väljumise ja kanalitest lahkumise sõnumitel:';
+$lang['settingsSoundChatBot'] = 'Chatboti sõnumite heli:';
+$lang['settingsSoundError'] = 'Veateate heli:';
+$lang['settingsBlink'] = 'Vilguta akna tiitlit uute sõnumite saabumisel:';
+$lang['settingsBlinkInterval'] = 'Vilgutamise intervall millisekundites:';
+$lang['settingsBlinkIntervalNumber'] = 'Vilksatuste arv intervallis:';
+$lang['playSelectedSound'] = 'Mängi valitud heli';
+$lang['requiresJavaScript'] = 'Vajalik on JavaScripti olemas olu jutuka kasutamiseks.';
+$lang['errorInvalidUser'] = 'Vigane kasutajanimi.';
+$lang['errorUserInUse'] = 'Kasutajanimi on juba võetud.';
+$lang['errorBanned'] = 'Kasutaja või IP on lisatud musta nimekirja.';
+$lang['errorMaxUsersLoggedIn'] = 'Jutukas on jõudnud maksimum kasutajate hulgani.';
+$lang['errorChatClosed'] = 'Jutukas on hetkel suletud.';
+$lang['logsTitle'] = 'ComicLand - jutukas - Logiraamat';
+$lang['logsDate'] = 'Kuupäev';
+$lang['logsTime'] = 'Kellaaeg';
+$lang['logsSearch'] = 'Otsi';
+$lang['logsPrivateChannels'] = 'Privaat-kanalid';
+$lang['logsPrivateMessages'] = 'Privaat-sõnumid';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/fa.php b/library/ajaxchat/chat/lib/lang/fa.php
new file mode 100644
index 000000000..0dc3cb132
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/fa.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author pepotiger (www.dd4bb.com)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'نام عبور';
+$lang['password'] = 'کلمه عبور';
+$lang['login'] = 'ورود';
+$lang['logout'] = 'خروج';
+$lang['channel'] = 'اطاق';
+$lang['style'] = 'ظاهر';
+$lang['language'] = 'زبان';
+$lang['inputLineBreak'] = 'کلید SHIFT+ENTER را برای ایجاد خط جدید فشار دهید';
+$lang['messageSubmit'] = 'ارسل';
+$lang['registeredUsers'] = 'کاربران ثبت نام شده';
+$lang['onlineUsers'] = 'کاربران حاضر';
+$lang['toggleAutoScroll'] = 'اسکرول اتوماتیک فعال/غیر فعال';
+$lang['toggleAudio'] = 'صدا روشن/خاموش';
+$lang['toggleHelp'] = 'نمایش/پنهان سازی کمک رسان';
+$lang['toggleSettings'] = 'نمایش/پنهان سازی تنظیمات';
+$lang['toggleOnlineList'] = 'نمایش/پنهان سازی لیست کاربران حاضر';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'اقتباس';
+$lang['bbCodeLabelCode'] = 'کد';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'تصویر';
+$lang['bbCodeLabelColor'] = 'رنگ خط';
+$lang['bbCodeTitleBold'] = 'متن درشت: [b]متن[/b]';
+$lang['bbCodeTitleItalic'] = 'متن کج: [i]متن[/i]';
+$lang['bbCodeTitleUnderline'] = 'زیر خط دار: [u]متن[/u]';
+$lang['bbCodeTitleQuote'] = 'نقل قول: [quote]متن[/quote] او [quote=الكاتب]نص[/quote]';
+$lang['bbCodeTitleCode'] = 'نمایش کد: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'وارد کردن آدرس: [url]http://example.org[/url] یا [url=http://example.org]متن[/url]';
+$lang['bbCodeTitleImg'] = 'وارد کردن تصویر: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'رنگ متن: [color=red]متن[/color]';
+$lang['help'] = 'کمک';
+$lang['helpItemDescJoin'] = 'ورود به اطاق:';
+$lang['helpItemCodeJoin'] = '/join نام اطاق';
+$lang['helpItemDescJoinCreate'] = 'ساخت اطاق خصوصی (تنها برای اعضا):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'دعوت کاربر (به عنوان مثال برای اطاق خصوصی):';
+$lang['helpItemCodeInvite'] = '/invite نام کاربری';
+$lang['helpItemDescUninvite'] = 'لغو دعوت:';
+$lang['helpItemCodeUninvite'] = '/uninvite نام کاربری';
+$lang['helpItemDescLogout'] = 'خروج:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'پیام خصوصی:';
+$lang['helpItemCodePrivateMessage'] = '/msg نامکاربری متن';
+$lang['helpItemDescQueryOpen'] = 'ساخت اطاق خصوصی:';
+$lang['helpItemCodeQueryOpen'] = '/query نام کاربری';
+$lang['helpItemDescQueryClose'] = 'خروج از اطاق خصوصی:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'شرح واقعه:';
+$lang['helpItemCodeAction'] = '/action متن';
+$lang['helpItemDescDescribe'] = 'شرح واقعه با پیام خصوصی:';
+$lang['helpItemCodeDescribe'] = '/describe نام کاربری متن';
+$lang['helpItemDescIgnore'] = 'قبول/صرف نظر پیغام از کاربر:';
+$lang['helpItemCodeIgnore'] = '/ignore نام کاربری';
+$lang['helpItemDescIgnoreList'] = 'افراد صرف نظر شده:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'نمایش اطاق کاربر:';
+$lang['helpItemCodeWhereis'] = '/whereis نام کاربر';
+$lang['helpItemDescKick'] = 'اجراج کاربر (تنها برای مدیران):';
+$lang['helpItemCodeKick'] = '/kick نام کاربری [زمان اخراج]';
+$lang['helpItemDescUnban'] = 'لغو اخراج (تنها برای مدیران):';
+$lang['helpItemCodeUnban'] = '/unban نام کاربری';
+$lang['helpItemDescBans'] = 'لیست کاربران اخراج شده (تنها برای مدیران):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'مشاهده آیپی کاربر (تنها برای مدیران):';
+$lang['helpItemCodeWhois'] = '/whois نام کاربری';
+$lang['helpItemDescWho'] = 'لیست کاربران حاضر:';
+$lang['helpItemCodeWho'] = '/who [نام اطاق]';
+$lang['helpItemDescList'] = 'نام اطاق های موجود:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Roll dice:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'تغییر نام کاربری:';
+$lang['helpItemCodeNick'] = '/nick نام کاربری';
+$lang['settings'] = 'تنظیمات';
+$lang['settingsBBCode'] = 'فعال سازی BBCode:';
+$lang['settingsBBCodeImages'] = 'فعال سازی تصاویر BBCode:';
+$lang['settingsBBCodeColors'] = 'فعال سازی رنگ متن BBCode:';
+$lang['settingsHyperLinks'] = 'فعال سازی لینک های اینترنتی:';
+$lang['settingsLineBreaks'] = 'فعال سازی پیام چند خطی:';
+$lang['settingsEmoticons'] = 'فعال سازی شکلک ها:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'حد اکثر تعداد پیام در هر اطاق:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'اجرای صدای انتخاب شده';
+$lang['requiresJavaScript'] = 'جاوا اسکریپت برای این تالار نیاز است.';
+$lang['errorInvalidUser'] = 'نا کاربری نامعتبر.';
+$lang['errorUserInUse'] = 'نام کاربری در حال استفاده است.';
+$lang['errorBanned'] = 'نام کاربری یا آیپی اخراج شده اند.';
+$lang['errorMaxUsersLoggedIn'] = 'متاسفانه تالار گفتگو به حداکثر ظرفیت خود برای کاربران حاضر رسیده است.';
+$lang['errorChatClosed'] = 'تالار گفتوگو هم اکنون بسته می باشد.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'تاریخ';
+$lang['logsTime'] = 'زمان';
+$lang['logsSearch'] = 'جست و جو';
+$lang['logsPrivateChannels'] = 'اطاق های خصوصی';
+$lang['logsPrivateMessages'] = 'پیغام های خصوصی';
+?>
diff --git a/library/ajaxchat/chat/lib/lang/fi.php b/library/ajaxchat/chat/lib/lang/fi.php
new file mode 100644
index 000000000..73466b412
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/fi.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Asmo Soinio
+ * @author Saku Laukkanen
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Käyttäjätunnus';
+$lang['password'] = 'Salasana';
+$lang['login'] = 'Kirjaudu sisään';
+$lang['logout'] = 'Kirjaudu ulos';
+$lang['channel'] = 'Kanava';
+$lang['style'] = 'Tyyli';
+$lang['language'] = 'Kieli';
+$lang['inputLineBreak'] = 'Paina SHIFT+ENTER saadaksesi rivinvaihdon';
+$lang['messageSubmit'] = 'Lähetä';
+$lang['registeredUsers'] = 'Rekisteröityneet käyttäjät';
+$lang['onlineUsers'] = 'Paikalla olevat käyttäjät';
+$lang['toggleAutoScroll'] = 'Automaattinen vieritys päällä/pois';
+$lang['toggleAudio'] = 'Äänet päällä/pois';
+$lang['toggleHelp'] = 'Näytä/piilota ohje';
+$lang['toggleSettings'] = 'Näytä/piilota asetukset';
+$lang['toggleOnlineList'] = 'Näytä/piilota paikalla olevat käyttäjät';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Lainaus';
+$lang['bbCodeLabelCode'] = 'Koodi';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Kuva';
+$lang['bbCodeLabelColor'] = 'Fontin väri';
+$lang['bbCodeTitleBold'] = 'Lihavoitu teksti: [b]teksti[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursivoitu teksti: [i]teksti[/i]';
+$lang['bbCodeTitleUnderline'] = 'Alleviivattu teksti: [u]teksti[/u]';
+$lang['bbCodeTitleQuote'] = 'Lainattu teksti: [quote]teksti[/quote] tai [quote=kirjoittaja]teksti[/quote]';
+$lang['bbCodeTitleCode'] = 'Koodi: [code]koodi[/code]';
+$lang['bbCodeTitleURL'] = 'Lisää linkki: [url]http://example.org[/url] tai [url=http://example.org]teksti[/url]';
+$lang['bbCodeTitleImg'] = 'Lisää kuva: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Kirjaisimen väri: [color=red]teksti[/color]';
+$lang['help'] = 'Ohje';
+$lang['helpItemDescJoin'] = 'Liity kanavalle:';
+$lang['helpItemCodeJoin'] = '/join KanavanNimi';
+$lang['helpItemDescJoinCreate'] = 'Tee uusi yksityinen kanava (Ainoastaan rekisteröityneille käyttäjille):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Kutsu joku (esim. Yksityiseen kanavaan):';
+$lang['helpItemCodeInvite'] = '/invite Käyttäjätunnus';
+$lang['helpItemDescUninvite'] = 'Peruuta kutsu:';
+$lang['helpItemCodeUninvite'] = '/uninvite Käyttäjätunnus';
+$lang['helpItemDescLogout'] = 'Kirjaudu ulos chatista:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Yksityisviesti:';
+$lang['helpItemCodePrivateMessage'] = '/msg Käyttäjätunnus Teksti';
+$lang['helpItemDescQueryOpen'] = 'Avaa yksityinen kanava:';
+$lang['helpItemCodeQueryOpen'] = '/query Käyttäjänimi';
+$lang['helpItemDescQueryClose'] = 'Sulje yksityinen kanava:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Kerro, mitä teet:';
+$lang['helpItemCodeAction'] = '/action Teksti';
+$lang['helpItemDescDescribe'] = 'Kerro yksityisviestissä mitä teet:';
+$lang['helpItemCodeDescribe'] = '/describe Käyttäjätunnus Teksti';
+$lang['helpItemDescIgnore'] = 'Estä tai salli viestejä käyttäjältä:';
+$lang['helpItemCodeIgnore'] = '/ignore Käyttäjänimi';
+$lang['helpItemDescIgnoreList'] = 'Listaa estetyt käyttäjät:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Näytä käyttäjän kanavat:';
+$lang['helpItemCodeWhereis'] = '/whereis Käyttäjänimi';
+$lang['helpItemDescKick'] = 'Potki käyttäjä (Ainoastaan Moderaattoreille):';
+$lang['helpItemCodeKick'] = '/kick Käyttäjänimi [Minuutteja potkittuna]';
+$lang['helpItemDescUnban'] = 'Poista käyttäjän potkut (Ainoastaan moderaattoreille):';
+$lang['helpItemCodeUnban'] = '/unban Käyttäjänimi';
+$lang['helpItemDescBans'] = 'Listaa potkitut käyttäjät (Ainoastaan moderaattoreille):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Näytä käyttäjän IP (Ainoastaan moderaattoreille):';
+$lang['helpItemCodeWhois'] = '/whois Käyttäjänimi';
+$lang['helpItemDescWho'] = 'Listaa käyttäjät jotka ovat paikalla:';
+$lang['helpItemCodeWho'] = '/who [Kanavatunnus]';
+$lang['helpItemDescList'] = 'Listaa käytettävissä olevat kanavat:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Heitä noppaa:';
+$lang['helpItemCodeRoll'] = '/roll [kertaa]d[sivuja]';
+$lang['helpItemDescNick'] = 'Vaihda käyttäjätunnusta:';
+$lang['helpItemCodeNick'] = '/nick Käyttäjänimi';
+$lang['settings'] = 'Asetukset';
+$lang['settingsBBCode'] = 'BBCode päälle:';
+$lang['settingsBBCodeImages'] = 'Salli kuvat:';
+$lang['settingsBBCodeColors'] = 'Salli värit:';
+$lang['settingsHyperLinks'] = 'Salli hyperlinkit:';
+$lang['settingsLineBreaks'] = 'Salli rivinvaihdot:';
+$lang['settingsEmoticons'] = 'Salli hymiöt:';
+$lang['settingsAutoFocus'] = 'Valitse tekstinsyöttökenttä automaattisesti:';
+$lang['settingsMaxMessages'] = 'Suurin määrä viestejä sivulla:';
+$lang['settingsWordWrap'] = 'Salli pitkien sanojen rivinvaihto:';
+$lang['settingsMaxWordLength'] = 'Sanan enimmäispituus ennen kuin riviä vaihdetaan:';
+$lang['settingsDateFormat'] = 'Ajan ja päivämäärän muoto:';
+$lang['settingsPersistFontColor'] = 'Pysyvä fontin väri:';
+$lang['settingsAudioVolume'] = 'Äänenvoimakkuus:';
+$lang['settingsSoundReceive'] = 'Ääni tuleville viesteille:';
+$lang['settingsSoundSend'] = 'Ääni lähteville viesteille:';
+$lang['settingsSoundEnter'] = 'Ääni sisäänkirjoittautumiseen ja kanavalle tuloon:';
+$lang['settingsSoundLeave'] = 'Ääni poistumiseen keskustelusta ja kanavalta:';
+$lang['settingsSoundChatBot'] = 'Ääni chatbotin viesteille:';
+$lang['settingsSoundError'] = 'Ääni virheilmoituksille:';
+$lang['settingsBlink'] = 'Vilkuta ikkunan nimeä uusista viesteistä:';
+$lang['settingsBlinkInterval'] = 'Vilkuttamisen aika millisekunneissa:';
+$lang['settingsBlinkIntervalNumber'] = 'Vilkutuksen viive:';
+$lang['playSelectedSound'] = 'Soita valittu ääni';
+$lang['requiresJavaScript'] = 'JavaScript on pakollinen tässä chatissa';
+$lang['errorInvalidUser'] = 'Virheellinen käyttäjänimi';
+$lang['errorUserInUse'] = 'Käyttäjänimi on käytössä, ole hyvä ja valitse toinen';
+$lang['errorBanned'] = 'Tällä IP:llä on porttikielto';
+$lang['errorMaxUsersLoggedIn'] = 'Chatissa on jo maksimimäärä käyttäjiä.';
+$lang['errorChatClosed'] = 'Chat on poistettu käytöstä toistaiseksi.';
+$lang['logsTitle'] = 'AJAX Chat-Lokitiedot';
+$lang['logsDate'] = 'Päivä';
+$lang['logsTime'] = 'Aika';
+$lang['logsSearch'] = 'Etsi';
+$lang['logsPrivateChannels'] = 'Näytä yksityiset kanavat';
+$lang['logsPrivateMessages'] = 'Yksityiset viestit';
+?>
diff --git a/library/ajaxchat/chat/lib/lang/fr.php b/library/ajaxchat/chat/lib/lang/fr.php
new file mode 100644
index 000000000..52ffaf1a2
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/fr.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Ettelcar
+ * @author Massimiliano Tiraboschi
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Nom d’utilisateur';
+$lang['password'] = 'Mot de passe';
+$lang['login'] = 'Connexion';
+$lang['logout'] = 'Déconnexion';
+$lang['channel'] = 'Salon';
+$lang['style'] = 'Style';
+$lang['language'] = 'Langue';
+$lang['inputLineBreak'] = 'Taper Maj + Entrer pour avoir une ligne blanche';
+$lang['messageSubmit'] = 'Envoyer';
+$lang['registeredUsers'] = 'Utilisateurs enregistrés';
+$lang['onlineUsers'] = 'Utilisateurs en ligne';
+$lang['toggleAutoScroll'] = 'Activer / Désactiver l’autoscroll';
+$lang['toggleAudio'] = 'Activer / Désactiver le son';
+$lang['toggleHelp'] = 'Afficher / Masquer l’aide';
+$lang['toggleSettings'] = 'Afficher / Masquer les préférences';
+$lang['toggleOnlineList'] = 'Afficher / Masquer les utilisateurs en ligne';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citation';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Couleur de police';
+$lang['bbCodeTitleBold'] = 'Texte en gras : [b]texte[/b]';
+$lang['bbCodeTitleItalic'] = 'Texte en italique : [i]texte[/i]';
+$lang['bbCodeTitleUnderline'] = 'Texte souligné : [u]texte[/u]';
+$lang['bbCodeTitleQuote'] = 'Citation : [quote]texte[/quote] ou [quote=auteur]texte[/quote]';
+$lang['bbCodeTitleCode'] = 'Affichage de code : [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Insérer une URL : [url]http://example.org[/url] ou [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insérer une image : [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Couleur de la police: [color=red]texte[/color]';
+$lang['help'] = 'Aide';
+$lang['helpItemDescJoin'] = 'Rejoindre un salon :';
+$lang['helpItemCodeJoin'] = '/join Nom_du_salon';
+$lang['helpItemDescJoinCreate'] = 'Créer un salon privé (Utilisateurs enregistrés seulement) :';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Inviter quelqu’un (exemple : rejoindre un salon privé) :';
+$lang['helpItemCodeInvite'] = '/invite Nom_d_utilisateur';
+$lang['helpItemDescUninvite'] = 'Annuler l’invitation :';
+$lang['helpItemCodeUninvite'] = '/uninvite Nom_d_utilisateur';
+$lang['helpItemDescLogout'] = 'Se déconnecter du chat :';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Message privé :';
+$lang['helpItemCodePrivateMessage'] = '/msg Nom_d_utilisateur Texte';
+$lang['helpItemDescQueryOpen'] = 'Ouvrir un canal privé :';
+$lang['helpItemCodeQueryOpen'] = '/query Nom_d_utilisateur';
+$lang['helpItemDescQueryClose'] = 'Fermer un canal privé:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Décrire une action :';
+$lang['helpItemCodeAction'] = '/action Texte';
+$lang['helpItemDescDescribe'] = 'Décrire une action dans un message privé :';
+$lang['helpItemCodeDescribe'] = '/describe Nom_d_utilisateur Texte';
+$lang['helpItemDescIgnore'] = 'Ignorer / Accepter les messages de l’utilisateur :';
+$lang['helpItemCodeIgnore'] = '/ignore Nom_d_utilisateur';
+$lang['helpItemDescIgnoreList'] = 'Liste des utilisateurs ignorés :';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel :';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Éjecter un utilisateur (Modérateurs seulement) :';
+$lang['helpItemCodeKick'] = '/kick Nom_d_utilisateur [Temps en minutes de ban]';
+$lang['helpItemDescUnban'] = 'Débannir un utilisateur (Modérateurs seulement) :';
+$lang['helpItemCodeUnban'] = '/unban Nom_d_utilisateur';
+$lang['helpItemDescBans'] = 'Liste des utilisateurs bannis (Modérateurs seulement) :';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Afficher l’adresse IP de l’utilisateur (Modérateurs seulement) :';
+$lang['helpItemCodeWhois'] = '/whois Nom_d_utilisateur';
+$lang['helpItemDescWho'] = 'Liste des utilisateurs en ligne :';
+$lang['helpItemCodeWho'] = '/who [Nom du salon]';
+$lang['helpItemDescList'] = 'Liste des salons disponibles :';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Jeter un dé :';
+$lang['helpItemCodeRoll'] = '/roll [nombre de dés]d[nombre de faces]';
+$lang['helpItemDescNick'] = 'Changer le nom d’utilisateur';
+$lang['helpItemCodeNick'] = '/nick Nom_d_utilisateur';
+$lang['settings'] = 'Préférences';
+$lang['settingsBBCode'] = 'Activer le BBCode :';
+$lang['settingsBBCodeImages'] = 'Activer le BBCode des images :';
+$lang['settingsBBCodeColors'] = 'Activer le BBCode pour la couleur de la police :';
+$lang['settingsHyperLinks'] = 'Activer les liens :';
+$lang['settingsLineBreaks'] = 'Activer les lignes blanches :';
+$lang['settingsEmoticons'] = 'Activer les émoticons :';
+$lang['settingsAutoFocus'] = 'Champ de saisie automatique :';
+$lang['settingsMaxMessages'] = 'Maximum de messages dans le chat :';
+$lang['settingsWordWrap'] = 'Activer la coupure des mots :';
+$lang['settingsMaxWordLength'] = 'Longueur maximum des mots :';
+$lang['settingsDateFormat'] = 'Format de la date :';
+$lang['settingsPersistFontColor'] = 'Garder la couleur du font :';
+$lang['settingsAudioVolume'] = 'Volume du son :';
+$lang['settingsSoundReceive'] = 'Son message entrant :';
+$lang['settingsSoundSend'] = 'Son message sortant :';
+$lang['settingsSoundEnter'] = 'Son pour connexion :';
+$lang['settingsSoundLeave'] = 'Son pour déconnexion :';
+$lang['settingsSoundChatBot'] = 'Son pour message robot :';
+$lang['settingsSoundError'] = 'Son pour les erreurs :';
+$lang['settingsBlink'] = 'Clignoter à chaque nouveau message :';
+$lang['settingsBlinkInterval'] = 'Intervalle de clignotage :';
+$lang['settingsBlinkIntervalNumber'] = 'Numéro de clignotage :';
+$lang['playSelectedSound'] = 'Jouer le son sélectionné';
+$lang['requiresJavaScript'] = 'Ce chat requiert JavasSript.';
+$lang['errorInvalidUser'] = 'Nom d’utilisateur incorrect.';
+$lang['errorUserInUse'] = 'Nom d’utilisateur déjà utilisé.';
+$lang['errorBanned'] = 'L’utilisateur ou l’adresse IP a été banni(e).';
+$lang['errorMaxUsersLoggedIn'] = 'Le chat a atteint le nombre maximal d’utilisateurs en ligne.';
+$lang['errorChatClosed'] = 'Le chat est fermé pour le moment.';
+$lang['logsTitle'] = 'Chat AJAX - Historique';
+$lang['logsDate'] = 'Date';
+$lang['logsTime'] = 'Heure';
+$lang['logsSearch'] = 'Chercher';
+$lang['logsPrivateChannels'] = 'Salons privés';
+$lang['logsPrivateMessages'] = 'Messages privés';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/gl.php b/library/ajaxchat/chat/lib/lang/gl.php
new file mode 100644
index 000000000..54b8a8ee6
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/gl.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Manu Quintans
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Usuario';
+$lang['password'] = 'Password';
+$lang['login'] = 'Entrar';
+$lang['logout'] = 'Pechar Sesión';
+$lang['channel'] = 'Canle';
+$lang['style'] = 'Estilo';
+$lang['language'] = 'Idioma';
+$lang['inputLineBreak'] = 'Prema SHIFT+ENTER para un salto de liña';
+$lang['messageSubmit'] = 'Enviar';
+$lang['registeredUsers'] = 'Usuarios rexistrados';
+$lang['onlineUsers'] = 'Usuarios Conectados';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sons on/off';
+$lang['toggleHelp'] = 'Amosar/Esconder ayuda';
+$lang['toggleSettings'] = 'Amosar/Esconder configuración';
+$lang['toggleOnlineList'] = 'Amosar/Esconder usuarios en liña';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Quote';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Imagen';
+$lang['bbCodeLabelColor'] = 'Color fonte';
+$lang['bbCodeTitleBold'] = 'Texto negriña: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Texto cursiva: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Texto subraiado: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Texto entrecomillado: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Mosrar código: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Insertar URL: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insertar imaxe: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Cor fonte: [color=red]text[/color]';
+$lang['help'] = 'Axuda';
+$lang['helpItemDescJoin'] = 'Entrar na canle:';
+$lang['helpItemCodeJoin'] = '/join nome da canle';
+$lang['helpItemDescJoinCreate'] = 'Crear un privado(So usuarios registrados):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Invitar a alguén(por ex. a un privado):';
+$lang['helpItemCodeInvite'] = '/invite Nome usuario';
+$lang['helpItemDescUninvite'] = 'Rechazar invitación:';
+$lang['helpItemCodeUninvite'] = '/uninvite Nome usuario';
+$lang['helpItemDescLogout'] = 'Pechar sesión:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Mensaxe Privada:';
+$lang['helpItemCodePrivateMessage'] = '/msg Usuario Texto';
+$lang['helpItemDescQueryOpen'] = 'Abrir unha canle privada:';
+$lang['helpItemCodeQueryOpen'] = '/query Usuario';
+$lang['helpItemDescQueryClose'] = 'Pechar canle privada:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Describe acción:';
+$lang['helpItemCodeAction'] = '/action Texto';
+$lang['helpItemDescDescribe'] = 'Describe acción nunha mensaxe privada:';
+$lang['helpItemCodeDescribe'] = '/describe Nome Usuario Texto';
+$lang['helpItemDescIgnore'] = 'Ignorar/Aceptar mensaxes de usuarios:';
+$lang['helpItemCodeIgnore'] = '/ignore Usuario';
+$lang['helpItemDescIgnoreList'] = 'Listar usuarios Ignorados:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Mostrar canle usuario:';
+$lang['helpItemCodeWhereis'] = '/whereis Usuario';
+$lang['helpItemDescKick'] = 'Banear usuario (Só moderadores):';
+$lang['helpItemCodeKick'] = '/kick Usuario [Minutos baneado]';
+$lang['helpItemDescUnban'] = 'Quitar ban usuario (Só moderadores):';
+$lang['helpItemCodeUnban'] = '/unban Nome usuario';
+$lang['helpItemDescBans'] = 'Listar usuarios baneados (Só moderadores):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Amosar ips de usuarios (So moderadores):';
+$lang['helpItemCodeWhois'] = '/whois Nome usuario';
+$lang['helpItemDescWho'] = 'Amosar usuarios conectados:';
+$lang['helpItemCodeWho'] = '/who [Nome canle]';
+$lang['helpItemDescList'] = 'Lista de canles disponibles:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Roll dice:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Cambiar Nome usuario:';
+$lang['helpItemCodeNick'] = '/nick Usuario';
+$lang['settings'] = 'Configuración';
+$lang['settingsBBCode'] = 'Activar BBCode:';
+$lang['settingsBBCodeImages'] = 'Activar imaxes BBCode:';
+$lang['settingsBBCodeColors'] = 'Activar cor fonte BBCode:';
+$lang['settingsHyperLinks'] = 'Activar enlaces:';
+$lang['settingsLineBreaks'] = 'Activar saltos de liña:';
+$lang['settingsEmoticons'] = 'Activar emoticonos:';
+$lang['settingsAutoFocus'] = 'Foco en campo de entrada automáticamente:';
+$lang['settingsMaxMessages'] = 'Máximo número de mensaxes:';
+$lang['settingsWordWrap'] = 'Activar wrapping en palabras largas:';
+$lang['settingsMaxWordLength'] = 'Máxima lonxutide de palabra antes de wrap:';
+$lang['settingsDateFormat'] = 'Formato de data e hora:';
+$lang['settingsPersistFontColor'] = 'Fixar cor de fonte:';
+$lang['settingsAudioVolume'] = 'Volume sons:';
+$lang['settingsSoundReceive'] = 'Son para mensaxes entrantes:';
+$lang['settingsSoundSend'] = 'Son para mensaxes salientes:';
+$lang['settingsSoundEnter'] = 'Son para login :';
+$lang['settingsSoundLeave'] = 'Son para logout :';
+$lang['settingsSoundChatBot'] = 'Son para mensaxes chat:';
+$lang['settingsSoundError'] = 'Son para errores:';
+$lang['settingsBlink'] = 'Parpadeo en ventá con novas mensaxes:';
+$lang['settingsBlinkInterval'] = 'Intervalo parpadeos (milisegundos):';
+$lang['settingsBlinkIntervalNumber'] = 'Número de parpadeos:';
+$lang['playSelectedSound'] = 'Executa son';
+$lang['requiresJavaScript'] = 'Necesitas ter activado o Javascript no teu navegador..';
+$lang['errorInvalidUser'] = 'Usuario Incorrecto.';
+$lang['errorUserInUse'] = 'Este Nome de usuario xa está sendo utilizado neste momento.';
+$lang['errorBanned'] = 'Usuario ou IP baneada..';
+$lang['errorMaxUsersLoggedIn'] = 'O chat alcanzou o número máximo de conexións.';
+$lang['errorChatClosed'] = 'Chat pechado neste momento.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Hora';
+$lang['logsSearch'] = 'Buscar';
+$lang['logsPrivateChannels'] = 'Canles privadas';
+$lang['logsPrivateMessages'] = 'mensaxes privadas';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/he.php b/library/ajaxchat/chat/lib/lang/he.php
new file mode 100644
index 000000000..39fa799d2
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/he.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Smiley Barry
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'שם משתמש';
+$lang['password'] = 'סיסמה';
+$lang['login'] = 'היכנס';
+$lang['logout'] = 'צא';
+$lang['channel'] = 'ערוץ';
+$lang['style'] = 'סגנון';
+$lang['language'] = 'לשון';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'שלח';
+$lang['registeredUsers'] = 'משתמשים רשומים';
+$lang['onlineUsers'] = 'משתמשים מחוברים';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'צטט';
+$lang['bbCodeLabelCode'] = 'קוד';
+$lang['bbCodeLabelURL'] = 'כתובת אינטרנט';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'צבע גופן';
+$lang['bbCodeTitleBold'] = 'טקסט מודגש: [b]טקסט[/b]';
+$lang['bbCodeTitleItalic'] = 'טקסט נטוי: [i]טקסט[/i]';
+$lang['bbCodeTitleUnderline'] = 'טקסט מודגש קו: [u]טקסט[/u]';
+$lang['bbCodeTitleQuote'] = 'צטט טקסט: [quote]טקסט[/quote] או [quote=כותב מקורי]טקסט[/quote]';
+$lang['bbCodeTitleCode'] = 'הראה קוד: [code]קוד[/code]';
+$lang['bbCodeTitleURL'] = 'הכנס כתובת: [url]http://www.example.org[/url] או[url=http://www.example.org]טקסט[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'צבע גופן: [color=צבע]טקסט[/color]';
+$lang['help'] = 'עזרה';
+$lang['helpItemDescJoin'] = 'הצטרף לערוץ:';
+$lang['helpItemCodeJoin'] = '/join שם ערוץ';
+$lang['helpItemDescJoinCreate'] = 'צור חדר פרטי (משתמשים רשומים בלבד):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'הזמן מישהו (דוגמא: חדר פרטי):';
+$lang['helpItemCodeInvite'] = '/invite שם_משתמש';
+$lang['helpItemDescUninvite'] = 'בטל הזמנה:';
+$lang['helpItemCodeUninvite'] = '/uninvite שם_משתמש';
+$lang['helpItemDescLogout'] = 'צא מהצאט:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'הודעה פרטית:';
+$lang['helpItemCodePrivateMessage'] = '/msg שם_משתמש טקסט';
+$lang['helpItemDescQueryOpen'] = 'פתח ערוץ אישי:';
+$lang['helpItemCodeQueryOpen'] = '/query שם_משתמש';
+$lang['helpItemDescQueryClose'] = 'סגור ערוץ אישי:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'תאר פעולה:';
+$lang['helpItemCodeAction'] = '/action טקסט';
+$lang['helpItemDescDescribe'] = 'תאר פעולה בהודעה פרטית:';
+$lang['helpItemCodeDescribe'] = '/describe שם_משתמש טקסט';
+$lang['helpItemDescIgnore'] = 'התעלם או קבל הודעות ממשתמש:';
+$lang['helpItemCodeIgnore'] = '/ignore שם_משתמש';
+$lang['helpItemDescIgnoreList'] = 'הראה רשימה של אנשים שאתה מתעלם מהם:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'העף משתמש (חברי צוות בלבד):';
+$lang['helpItemCodeKick'] = '/kick שם_משתמש [מספר דקות]';
+$lang['helpItemDescUnban'] = 'בטל חסימת משתמש (חברי צוות בלבד):';
+$lang['helpItemCodeUnban'] = '/unban שם_משתמש';
+$lang['helpItemDescBans'] = 'הראה רשימת משתמשים חסומים (חברי צוות בלבד):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'הראה כתובת מחשב של משתמש (חברי צוות בלבד):';
+$lang['helpItemCodeWhois'] = '/whois שם_משתמש';
+$lang['helpItemDescWho'] = 'הראה רשימת משתמשים מחוברים:';
+$lang['helpItemCodeWho'] = '/who שם_ערוץ';
+$lang['helpItemDescList'] = 'הראה רשימת ערוצים פתוחים:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'גלגל קוביה:';
+$lang['helpItemCodeRoll'] = '/roll [מספר]d[צדדים]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'JavaScript נצרך בשביל הצאט הזה.';
+$lang['errorInvalidUser'] = 'שם משתמש לא חוקי.';
+$lang['errorUserInUse'] = 'שם משתמש בשימוש.';
+$lang['errorBanned'] = 'משתמש או כתובת מחשב חסומים.';
+$lang['errorMaxUsersLoggedIn'] = 'הצאט כרגע מלא.';
+$lang['errorChatClosed'] = 'הצאט כרגע סגור.';
+$lang['logsTitle'] = 'תיעוד';
+$lang['logsDate'] = 'תאריך';
+$lang['logsTime'] = 'זמן';
+$lang['logsSearch'] = 'חיפוש';
+$lang['logsPrivateChannels'] = 'ערוצים פרטיים';
+$lang['logsPrivateMessages'] = 'הודעות פרטיות';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/hr.php b/library/ajaxchat/chat/lib/lang/hr.php
new file mode 100644
index 000000000..ed0451033
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/hr.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Brbljanje';
+$lang['userName'] = 'Korisničko ime';
+$lang['password'] = 'Lozinka';
+$lang['login'] = 'Prijava';
+$lang['logout'] = 'Odjava';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Jezik';
+$lang['inputLineBreak'] = 'Za unos novog retka pritisnite SHIFT+ENTER';
+$lang['messageSubmit'] = 'Pošalji';
+$lang['registeredUsers'] = 'Registrirani korisnici';
+$lang['onlineUsers'] = 'Prisutni korisnici';
+$lang['toggleAutoScroll'] = 'Automatsko klizanje - uklj/isklj ';
+$lang['toggleAudio'] = 'Zvuk - uklj/isklj';
+$lang['toggleHelp'] = 'Pomoć - prikaži/sakrij';
+$lang['toggleSettings'] = 'Postavke - prikaži/sakrij';
+$lang['toggleOnlineList'] = 'Popisa prisutnih - prikaži/sakrij';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citat';
+$lang['bbCodeLabelCode'] = 'Kôd';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Slika';
+$lang['bbCodeLabelColor'] = 'Boja';
+$lang['bbCodeTitleBold'] = 'Snažan tekst: [b]tekst[/b]';
+$lang['bbCodeTitleItalic'] = 'Kurziv: [i]tekst[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podvučeni tekst: [u]tekst[/u]';
+$lang['bbCodeTitleQuote'] = 'Citirani tekst: [quote]tekst[/quote] ili [quote=autor]tekst[/quote]';
+$lang['bbCodeTitleCode'] = 'Prikaz kôda: [code]kôd[/code]';
+$lang['bbCodeTitleURL'] = 'Umetanje URL: [url]http://primjer.org[/url] ili [url=http://primjer.org]tekst[/url]';
+$lang['bbCodeTitleImg'] = 'Umetanje slike: [img]http://primjer.org/slika.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Boja fonta: [color=red]tekst[/color]';
+$lang['help'] = 'Pomoć';
+$lang['helpItemDescJoin'] = 'Pridruživanje kanalu:';
+$lang['helpItemCodeJoin'] = '/join kanal';
+$lang['helpItemDescJoinCreate'] = 'Izrada privatne sobe (samo za registrirane korisnike):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Pozivanje korisnika (npr. u privatnu sobu):';
+$lang['helpItemCodeInvite'] = '/invite korisnik';
+$lang['helpItemDescUninvite'] = 'Opoziv:';
+$lang['helpItemCodeUninvite'] = '/uninvite korisnik';
+$lang['helpItemDescLogout'] = 'Odjava iz brbljanja:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privatna poruka:';
+$lang['helpItemCodePrivateMessage'] = '/msg korisnik tekst';
+$lang['helpItemDescQueryOpen'] = 'Otvaranje privatnog kanala:';
+$lang['helpItemCodeQueryOpen'] = '/query korisnik';
+$lang['helpItemDescQueryClose'] = 'Zatvaranje privatnog kanala:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Aktivnost:';
+$lang['helpItemCodeAction'] = '/action tekst';
+$lang['helpItemDescDescribe'] = 'Aktivnost u privatnoj poruci:';
+$lang['helpItemCodeDescribe'] = '/describe korisnik tekst';
+$lang['helpItemDescIgnore'] = 'Ignoriranje/prihvaćanje poruka od korisnika:';
+$lang['helpItemCodeIgnore'] = '/ignore korisnik';
+$lang['helpItemDescIgnoreList'] = 'Ispisivanje ignoriranih korisnika:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Prikazivanje korisničkog kanala:';
+$lang['helpItemCodeWhereis'] = '/whereis korisnik';
+$lang['helpItemDescKick'] = 'Progon korisnika (samo za moderatore):';
+$lang['helpItemCodeKick'] = '/kick korisnik [minute]';
+$lang['helpItemDescUnban'] = 'Uklanjanje zabrane korisnika (samo za moderatore):';
+$lang['helpItemCodeUnban'] = '/unban korisnik';
+$lang['helpItemDescBans'] = 'Ispisivanje zabranjenih korisnika (samo za moderatore):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Prikazivanje IP korisnika (samo za moderatore):';
+$lang['helpItemCodeWhois'] = '/whois korisnik';
+$lang['helpItemDescWho'] = 'Ispisivanje prisutnih korisnika:';
+$lang['helpItemCodeWho'] = '/who [kanal]';
+$lang['helpItemDescList'] = 'Ispisivanje dostupnih kanala:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Bacanje kocke:';
+$lang['helpItemCodeRoll'] = '/roll [broj]d[strane]';
+$lang['helpItemDescNick'] = 'Promjena korisničkog imena:';
+$lang['helpItemCodeNick'] = '/nick korisnik';
+$lang['settings'] = 'Postavke';
+$lang['settingsBBCode'] = 'Omogući BB kôd:';
+$lang['settingsBBCodeImages'] = 'Omogući BB kôd za slike:';
+$lang['settingsBBCodeColors'] = 'Omogući BB kôd za boju fonta:';
+$lang['settingsHyperLinks'] = 'Omogući hiperveze:';
+$lang['settingsLineBreaks'] = 'Omogući nove retke:';
+$lang['settingsEmoticons'] = 'Omogući emotikone:';
+$lang['settingsAutoFocus'] = 'Automatski postavi fokus u polje unosa:';
+$lang['settingsMaxMessages'] = 'Najveći broj poruka na popisu:';
+$lang['settingsWordWrap'] = 'Omogući obmatanje dugih riječi:';
+$lang['settingsMaxWordLength'] = 'Najveća duljina riječi prije njezinog obmatanja:';
+$lang['settingsDateFormat'] = 'Oblikovanje datuma i vremena:';
+$lang['settingsPersistFontColor'] = 'Dosljedna boja fonta:';
+$lang['settingsAudioVolume'] = 'Glasnoća zvuka:';
+$lang['settingsSoundReceive'] = 'Zvuk za dolazne poruke:';
+$lang['settingsSoundSend'] = 'Zvuk za odlazne poruke:';
+$lang['settingsSoundEnter'] = 'Zvuk za prijavljivanje i poruke pristupanja kanalu:';
+$lang['settingsSoundLeave'] = 'Zvuk za odjavljivanje i poruke napuštanja kanala:';
+$lang['settingsSoundChatBot'] = 'Zvuk za poruke brbljobota:';
+$lang['settingsSoundError'] = 'Zvuk za poruke pogreške:';
+$lang['settingsBlink'] = 'Treptanje naslova prozora kod novih poruka:';
+$lang['settingsBlinkInterval'] = 'Trajanje treptanja (u milisekundama):';
+$lang['settingsBlinkIntervalNumber'] = 'Broj treptanja:';
+$lang['playSelectedSound'] = 'Pokreni odabrani zvuk';
+$lang['requiresJavaScript'] = 'Ovo brbljanje zahtjeva JavaScript.';
+$lang['errorInvalidUser'] = 'Nepravilno korisničko ime.';
+$lang['errorUserInUse'] = 'Korisničko ime već je u upotrebi.';
+$lang['errorBanned'] = 'Korisnik ili IP je zabranjen.';
+$lang['errorMaxUsersLoggedIn'] = 'Brbljaonica je dostigla najveći dopušteni broj prijavljenih korisnika.';
+$lang['errorChatClosed'] = 'Brbljaonica je trenutno zatvorena.';
+$lang['logsTitle'] = 'AJAX Brbljanje - Zapisnici';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Vrijeme';
+$lang['logsSearch'] = 'Traži';
+$lang['logsPrivateChannels'] = 'Privatni kanali';
+$lang['logsPrivateMessages'] = 'Privatne poruke';
+?>
diff --git a/library/ajaxchat/chat/lib/lang/hu.php b/library/ajaxchat/chat/lib/lang/hu.php
new file mode 100644
index 000000000..5f2174134
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/hu.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Felhasználónév';
+$lang['password'] = 'Jelszó';
+$lang['login'] = 'Belépés';
+$lang['logout'] = 'Kilépés';
+$lang['channel'] = 'Szoba';
+$lang['style'] = 'Stílus';
+$lang['language'] = 'Nyelv';
+$lang['inputLineBreak'] = 'Üsse le a SHIFT+ENTER billentyűket sortöréshez';
+$lang['messageSubmit'] = 'Küldés';
+$lang['registeredUsers'] = 'Regisztrált felhasználók';
+$lang['onlineUsers'] = 'Jelenlévők';
+$lang['toggleAutoScroll'] = 'Automatikus görgetés be/ki';
+$lang['toggleAudio'] = 'Hang be/ki';
+$lang['toggleHelp'] = 'Segítség mutatása/elrejtése';
+$lang['toggleSettings'] = 'Beállítások mutatása/elrejtése';
+$lang['toggleOnlineList'] = 'Jelenlévők mutatása/elrejtése';
+$lang['bbCodeLabelBold'] = 'B';
+$lang['bbCodeLabelItalic'] = 'I';
+$lang['bbCodeLabelUnderline'] = 'U';
+$lang['bbCodeLabelQuote'] = 'Idézet';
+$lang['bbCodeLabelCode'] = 'Kód';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Kép';
+$lang['bbCodeLabelColor'] = 'Szöveg szín';
+$lang['bbCodeTitleBold'] = 'Félkövér szöveg: [b]szöveg[/b]';
+$lang['bbCodeTitleItalic'] = 'Dőlt szöveg: [i]szöveg[/i]';
+$lang['bbCodeTitleUnderline'] = 'Aláhúzott szöveg: [u]szöveg[/u]';
+$lang['bbCodeTitleQuote'] = 'Idézett szöveg: [quote]szöveg[/quote] vagy [quote=szerző]szöveg[/quote]';
+$lang['bbCodeTitleCode'] = 'Kód: [code]kód[/code]';
+$lang['bbCodeTitleURL'] = 'URL beszúrása: [url]http://example.org[/url] vagy [url=http://example.org]szöveg[/url]';
+$lang['bbCodeTitleImg'] = 'Kép beszúrása: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Szöveg szín: [color=red]szöveg[/color]';
+$lang['help'] = 'Segítség';
+$lang['helpItemDescJoin'] = 'Belépés a szobába:';
+$lang['helpItemCodeJoin'] = '/join Szobanév';
+$lang['helpItemDescJoinCreate'] = 'Privát szoba létrehozása (Csak regisztráltaknak):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Meghívás (pl. privát szobába):';
+$lang['helpItemCodeInvite'] = '/invite Nick';
+$lang['helpItemDescUninvite'] = 'Meghívás megszüntetése:';
+$lang['helpItemCodeUninvite'] = '/uninvite Nick';
+$lang['helpItemDescLogout'] = 'Kilépés a chatből:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privát üzenet:';
+$lang['helpItemCodePrivateMessage'] = '/msg Nick szöveg';
+$lang['helpItemDescQueryOpen'] = 'Privát szoba létrehozása:';
+$lang['helpItemCodeQueryOpen'] = '/query Nick';
+$lang['helpItemDescQueryClose'] = 'Privát szoba beázárása:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Akció írása (E/3 személyű beszéd):';
+$lang['helpItemCodeAction'] = '/action szöveg';
+$lang['helpItemDescDescribe'] = 'Akció privát beszélgetésben:';
+$lang['helpItemCodeDescribe'] = '/describe Nick szöveg';
+$lang['helpItemDescIgnore'] = 'Felhasználó figyelembe vétele/figyelmen kívül hagyása:';
+$lang['helpItemCodeIgnore'] = '/ignore Nick';
+$lang['helpItemDescIgnoreList'] = 'Figyelmen kívül hagyottak listája:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'A felhasználó mely szobákban tartózkodik:';
+$lang['helpItemCodeWhereis'] = '/whereis Nick';
+$lang['helpItemDescKick'] = 'Felhasználó kirúgása (Csak moderátorok):';
+$lang['helpItemCodeKick'] = '/kick Nick [kitiltás percekben]';
+$lang['helpItemDescUnban'] = 'Tiltás feloldása (Csak moderátorok):';
+$lang['helpItemCodeUnban'] = '/unban Nick';
+$lang['helpItemDescBans'] = 'Kitiltottak listája (Csak moderátorok):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Felhasználó IP címének mutatása (Csak moderátorok):';
+$lang['helpItemCodeWhois'] = '/whois Nick';
+$lang['helpItemDescWho'] = 'Jelenlévők listázása:';
+$lang['helpItemCodeWho'] = '/who [Szobanév]';
+$lang['helpItemDescList'] = 'Szobák listázása:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Dobókocka dobás:';
+$lang['helpItemCodeRoll'] = '/roll [szám]d[oldalak]';
+$lang['helpItemDescNick'] = 'Nick cseréje:';
+$lang['helpItemCodeNick'] = '/nick Nick';
+$lang['settings'] = 'Beállítások';
+$lang['settingsBBCode'] = 'BBCode engedélyezése:';
+$lang['settingsBBCodeImages'] = 'Kép BBCode engedélyezése:';
+$lang['settingsBBCodeColors'] = 'Szöveg szín BBCode engedélyezése:';
+$lang['settingsHyperLinks'] = 'Linkek engedélyezése:';
+$lang['settingsLineBreaks'] = 'Sortörések engedélyezése:';
+$lang['settingsEmoticons'] = 'Emotikonok engedélyezése:';
+$lang['settingsAutoFocus'] = 'Automatikusan a beviteli mezőn legyen a fókusz:';
+$lang['settingsMaxMessages'] = 'Maximálisan látható üzenetek száma:';
+$lang['settingsWordWrap'] = 'Hosszú szavak tördelése:';
+$lang['settingsMaxWordLength'] = 'Maximális karakterszám egy szó tördelése előtt:';
+$lang['settingsDateFormat'] = 'Dátum és idő kijelzésének formátuma:';
+$lang['settingsPersistFontColor'] = 'Folyamatos betűszín használata:';
+$lang['settingsAudioVolume'] = 'Hangerő:';
+$lang['settingsSoundReceive'] = 'Bejövő üzenetek hangja:';
+$lang['settingsSoundSend'] = 'Kimenő üzenetek hangja:';
+$lang['settingsSoundEnter'] = 'Belépés szobaüzenetek hangja:';
+$lang['settingsSoundLeave'] = 'Kilépés szobaüzenetek hangja:';
+$lang['settingsSoundChatBot'] = 'ChatBot üzenetek hangja:';
+$lang['settingsSoundError'] = 'Hibaüzenetek hangja:';
+$lang['settingsBlink'] = 'Ablak fejléce villogjon új üzenet esetén:';
+$lang['settingsBlinkInterval'] = 'A villogás intervallumának hossza századmásodpercekben:';
+$lang['settingsBlinkIntervalNumber'] = 'Villogási intervallumok száma:';
+$lang['playSelectedSound'] = 'Kiválasztott hang lejátszása';
+$lang['requiresJavaScript'] = 'A JavaScript bekapcsolása szükséges a chat használatához.';
+$lang['errorInvalidUser'] = 'Hamis Nick.';
+$lang['errorUserInUse'] = 'A nick már használatban van.';
+$lang['errorBanned'] = 'Ez a felhasználó vagy IP ki van tiltva.';
+$lang['errorMaxUsersLoggedIn'] = 'A chatelők száma elérte a megengedett maximumot.';
+$lang['errorChatClosed'] = 'A chat jelenleg nem üzemel.';
+$lang['logsTitle'] = 'AJAX Chat - Logok';
+$lang['logsDate'] = 'Dátum';
+$lang['logsTime'] = 'Idő';
+$lang['logsSearch'] = 'Keresés';
+$lang['logsPrivateChannels'] = 'Privát szobák';
+$lang['logsPrivateMessages'] = 'Privát üzenetek';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/in.php b/library/ajaxchat/chat/lib/lang/in.php
new file mode 100644
index 000000000..175cc904b
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/in.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Nama';
+$lang['password'] = 'Password';
+$lang['login'] = 'Masuk';
+$lang['logout'] = 'Keluar';
+$lang['channel'] = 'Channel';
+$lang['style'] = 'Model';
+$lang['language'] = 'Bahasa';
+$lang['inputLineBreak'] = 'Tekan SHIFT+ENTER untuk berpindah baris';
+$lang['messageSubmit'] = 'Tampilkan';
+$lang['registeredUsers'] = 'Pemakai Terdaftar';
+$lang['onlineUsers'] = 'Pemakai Online';
+$lang['toggleAutoScroll'] = 'Scroll Otomatis on/off';
+$lang['toggleAudio'] = 'Suara on/off';
+$lang['toggleHelp'] = 'Tampilkan/Sembunyikan help';
+$lang['toggleSettings'] = 'Tampilkan/Sembunyikan settings';
+$lang['toggleOnlineList'] = 'Tampilkan/Sembunyikan daftar online';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Salin';
+$lang['bbCodeLabelCode'] = 'Kode';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Gambar';
+$lang['bbCodeLabelColor'] = 'Warna Huruf';
+$lang['bbCodeTitleBold'] = 'Huruf Tebal: [b]kata[/b]';
+$lang['bbCodeTitleItalic'] = 'Huruf Miring: [i]kata[/i]';
+$lang['bbCodeTitleUnderline'] = 'Garis Bawah: [u]kata[/u]';
+$lang['bbCodeTitleQuote'] = 'Kata Saduran: [quote]kata[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Code display: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Sisip URL: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Sisip gambar: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Warna Huruf: [color=red]text[/color]';
+$lang['help'] = 'Help';
+$lang['helpItemDescJoin'] = 'Gabung Channel:';
+$lang['helpItemCodeJoin'] = '/join NamaChannel';
+$lang['helpItemDescJoinCreate'] = 'Buat ruang privasi (Hanya untuk pengguna terdaftar):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Mengundang Seseorang (mis: ke ruang privasi):';
+$lang['helpItemCodeInvite'] = '/invite NamaPengguna';
+$lang['helpItemDescUninvite'] = 'Batalkan Undangan:';
+$lang['helpItemCodeUninvite'] = '/uninvite NamaPengguna';
+$lang['helpItemDescLogout'] = 'Keluar dari Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Pesan Pribadi:';
+$lang['helpItemCodePrivateMessage'] = '/msg NamaPengguna Teks';
+$lang['helpItemDescQueryOpen'] = 'Membuka Channel Privasi:';
+$lang['helpItemCodeQueryOpen'] = '/query NamaPengguna';
+$lang['helpItemDescQueryClose'] = 'Menutup Channel Privasi:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Menjelaskan Tindakan:';
+$lang['helpItemCodeAction'] = '/action Teks';
+$lang['helpItemDescDescribe'] = 'Menjelaskan Tindakan pada pesan pribadi:';
+$lang['helpItemCodeDescribe'] = '/describe NamaPengguna Teks';
+$lang['helpItemDescIgnore'] = 'Mengacuhkan/Menerima Pesan Dari Pengguna Lain:';
+$lang['helpItemCodeIgnore'] = '/ignore NamaPengguna';
+$lang['helpItemDescIgnoreList'] = 'Tampilkan Daftar Pengguna yang Diacuhkan:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Tampilkan Pengguna di Channel:';
+$lang['helpItemCodeWhereis'] = '/whereis NamaPengguna';
+$lang['helpItemDescKick'] = 'Menendang Pengguna (Hanya Untuk Moderator):';
+$lang['helpItemCodeKick'] = '/kick NamaPengguna [Jumlah Menit Hukuman]';
+$lang['helpItemDescUnban'] = 'Membatalkan Blok Pengguna (Hanya Untuk Moderator):';
+$lang['helpItemCodeUnban'] = '/unban NamaPengguna';
+$lang['helpItemDescBans'] = 'Tampilkan Daftar Pengguna yang diblok (Hanya Untuk Moderator):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Tampilkan IP Pengguna (Hanya Untuk Moderator):';
+$lang['helpItemCodeWhois'] = '/whois NamaPengguna';
+$lang['helpItemDescWho'] = 'Tampilkan Daftar Pengguna di Channel:';
+$lang['helpItemCodeWho'] = '/who [NamaChannel]';
+$lang['helpItemDescList'] = 'Tampilkan Daftar Channel Yang Tersedia:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Lempar Dadu:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Mengganti Nama:';
+$lang['helpItemCodeNick'] = '/nick Nama';
+$lang['settings'] = 'Pengaturan';
+$lang['settingsBBCode'] = 'Membolehkan BBCode:';
+$lang['settingsBBCodeImages'] = 'Membolehkan gambar BBCode:';
+$lang['settingsBBCodeColors'] = 'Membolehkan warna huruf BBCode:';
+$lang['settingsHyperLinks'] = 'Membolehkan hyperlinks:';
+$lang['settingsLineBreaks'] = 'Membolehkan line breaks:';
+$lang['settingsEmoticons'] = 'Membolehkan emoticons:';
+$lang['settingsAutoFocus'] = 'Mengatur fokus secara otomatis ke kotak input:';
+$lang['settingsMaxMessages'] = 'Jumlah Pesan Maksimum pada daftar Chat:';
+$lang['settingsWordWrap'] = 'Membolehkan memecah suku kata yang panjang:';
+$lang['settingsMaxWordLength'] = 'Panjang maksimum sebuah kata sebelum dipecah:';
+$lang['settingsDateFormat'] = 'Format dari tampilan tanggal dan waktu:';
+$lang['settingsPersistFontColor'] = 'Mempertahankan Warna Huruf:';
+$lang['settingsAudioVolume'] = 'Volume Suara:';
+$lang['settingsSoundReceive'] = 'Suara pada saat pesan masuk:';
+$lang['settingsSoundSend'] = 'Suara pada saat pesan keluar:';
+$lang['settingsSoundEnter'] = 'Suara pada saat masuk channel:';
+$lang['settingsSoundLeave'] = 'Suara pada saat keluar Channel:';
+$lang['settingsSoundChatBot'] = 'Suara pada saat ChatBot:';
+$lang['settingsSoundError'] = 'Suara pada saat terdapat kesalahan:';
+$lang['settingsBlink'] = 'Kedipkan Judul Jendela pada saat ada pesan baru:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Jumlah interval kedipan:';
+$lang['playSelectedSound'] = 'Mainkan suara yang dipilih';
+$lang['requiresJavaScript'] = 'JavaScript diperlukan untuk Chat ini.';
+$lang['errorInvalidUser'] = 'Nama Salah.';
+$lang['errorUserInUse'] = 'Nama sudah ada yang pakai.';
+$lang['errorBanned'] = 'Pengguna atau IP diblok.';
+$lang['errorMaxUsersLoggedIn'] = 'Saluran Chat telah mencapai jumlah maksimum pengguna.';
+$lang['errorChatClosed'] = 'Saluran Chat ditutup sementara.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Tanggal';
+$lang['logsTime'] = 'Waktu';
+$lang['logsSearch'] = 'Cari';
+$lang['logsPrivateChannels'] = 'Saluran-saluran privasi';
+$lang['logsPrivateMessages'] = 'Pesan Pribadi';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/it.php b/library/ajaxchat/chat/lib/lang/it.php
new file mode 100644
index 000000000..abcd4f9db
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/it.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author s8s8
+ * @author Massimiliano Tiraboschi
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Nome';
+$lang['password'] = 'Password';
+$lang['login'] = 'Login';
+$lang['logout'] = 'Uscita';
+$lang['channel'] = 'Canale';
+$lang['style'] = 'Stile';
+$lang['language'] = 'Lingua';
+$lang['inputLineBreak'] = 'Premi SHIFT+ENTER per inserire una linea vuota';
+$lang['messageSubmit'] = 'Invia';
+$lang['registeredUsers'] = 'Utente registrato';
+$lang['onlineUsers'] = 'Utenti Online';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Suono on/off';
+$lang['toggleHelp'] = 'Mostra/Nascondi aiuto';
+$lang['toggleSettings'] = 'Mostra/Nascondi preferenze';
+$lang['toggleOnlineList'] = 'Mostra/Nascondi lista utenti online';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Cita';
+$lang['bbCodeLabelCode'] = 'Codice';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Colore Testo';
+$lang['bbCodeTitleBold'] = 'Grassetto: [b]testo[/b]';
+$lang['bbCodeTitleItalic'] = 'Corsivo: [i]testo[/i]';
+$lang['bbCodeTitleUnderline'] = 'Sottolineato: [u]testo[/u]';
+$lang['bbCodeTitleQuote'] = 'Cita: [quote]testo[/quote] oppure [quote=autore]testo[/quote]';
+$lang['bbCodeTitleCode'] = 'Mostra Codice: [code]codice[/code]';
+$lang['bbCodeTitleURL'] = 'Inserire URL: [url]http://example.org/[/url] oppure [url=http://example.org/]testo[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Colore Testo: [color=red]testo[/color]';
+$lang['help'] = 'Aiuto';
+$lang['helpItemDescJoin'] = 'Entra nel canale:';
+$lang['helpItemCodeJoin'] = '/join NomeCanale';
+$lang['helpItemDescJoinCreate'] = 'Crea un canale privato (Solo utenti registrati):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Invita qualcuno (e.g. in un canale privato):';
+$lang['helpItemCodeInvite'] = '/invite Username';
+$lang['helpItemDescUninvite'] = 'Rimuovi invito:';
+$lang['helpItemCodeUninvite'] = '/uninvite Username';
+$lang['helpItemDescLogout'] = 'Esce dalla Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Messaggio privato:';
+$lang['helpItemCodePrivateMessage'] = '/msg NomeUtente Testo';
+$lang['helpItemDescQueryOpen'] = 'Apre un canale privato:';
+$lang['helpItemCodeQueryOpen'] = '/query NomeUtente';
+$lang['helpItemDescQueryClose'] = 'Chiude un canale privato:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Descrive azione:';
+$lang['helpItemCodeAction'] = '/action Testo';
+$lang['helpItemDescDescribe'] = 'Descrive azioni in messaggi privati:';
+$lang['helpItemCodeDescribe'] = '/describe NomeUtente Testo';
+$lang['helpItemDescIgnore'] = 'Ignora/accetta messaggi di un Utente:';
+$lang['helpItemCodeIgnore'] = '/ignore NomeUtente';
+$lang['helpItemDescIgnoreList'] = 'Elenca la lista degli ignorati:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Fa uscire un Utente (Solo Moderatore):';
+$lang['helpItemCodeKick'] = '/kick NomeUtente [Minuti bannato]';
+$lang['helpItemDescUnban'] = 'Toglie il Ban a un Utente (Solo Moderatore):';
+$lang['helpItemCodeUnban'] = '/unban NomeUtente';
+$lang['helpItemDescBans'] = 'Lista Utenti Bannati (Solo Moderatore):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Mostra IP Utente (Solo Moderatore):';
+$lang['helpItemCodeWhois'] = '/whois NomeUtente';
+$lang['helpItemDescWho'] = 'Lista Utenti in linea:';
+$lang['helpItemCodeWho'] = '/who [NomeCanale]';
+$lang['helpItemDescList'] = 'Lista canali disponibili:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Lancia i dadi:';
+$lang['helpItemCodeRoll'] = '/roll [quantita]d[faccie]';
+$lang['helpItemDescNick'] = 'Cambia username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Preferenze';
+$lang['settingsBBCode'] = 'Attiva BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Attiva hyperlinks:';
+$lang['settingsLineBreaks'] = 'Attiva linee bianche:';
+$lang['settingsEmoticons'] = 'Attiva emoticons:';
+$lang['settingsAutoFocus'] = 'Focus messaggio automatico:';
+$lang['settingsMaxMessages'] = 'Max messaggi in chat:';
+$lang['settingsWordWrap'] = 'Attiva taglio parole lunghe:';
+$lang['settingsMaxWordLength'] = 'Lunghezza massima parole:';
+$lang['settingsDateFormat'] = 'Formato data ed ora:';
+$lang['settingsPersistFontColor'] = 'Colore font persistente:';
+$lang['settingsAudioVolume'] = 'Volume suono:';
+$lang['settingsSoundReceive'] = 'Suono messaggi entranti:';
+$lang['settingsSoundSend'] = 'Suono messaggi uscenti:';
+$lang['settingsSoundEnter'] = 'Suono per login:';
+$lang['settingsSoundLeave'] = 'Suono per uscita:';
+$lang['settingsSoundChatBot'] = 'Suono per messaggi robot:';
+$lang['settingsSoundError'] = 'Suono per messaggi errore:';
+$lang['settingsBlink'] = 'Lampeggio nuovi messaggi:';
+$lang['settingsBlinkInterval'] = 'Intervallo lampeggio:';
+$lang['settingsBlinkIntervalNumber'] = 'Numero massimo lampeggi:';
+$lang['playSelectedSound'] = 'Esegui suono selezionato';
+$lang['requiresJavaScript'] = 'Serve il JavaScript per questa Chat.';
+$lang['errorInvalidUser'] = 'Nome utente non valido.';
+$lang['errorUserInUse'] = 'Nome utente in uso.';
+$lang['errorBanned'] = 'Utente o IP bannato.';
+$lang['errorMaxUsersLoggedIn'] = 'La chat ha raggiunto il massimo numero di utenti connessi.';
+$lang['errorChatClosed'] = 'La chat è chiusa in questo momento.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Ora';
+$lang['logsSearch'] = 'Cerca';
+$lang['logsPrivateChannels'] = 'Canali Privati';
+$lang['logsPrivateMessages'] = 'Messaggi privati';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ja.php b/library/ajaxchat/chat/lib/lang/ja.php
new file mode 100644
index 000000000..075fc4fcb
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ja.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'ユーザー名';
+$lang['password'] = 'パスワード';
+$lang['login'] = 'ログイン';
+$lang['logout'] = 'ログアウト';
+$lang['channel'] = 'チャンネル';
+$lang['style'] = 'スタイル';
+$lang['language'] = '言語';
+$lang['inputLineBreak'] = 'SHIFT+ENTER で改行できます';
+$lang['messageSubmit'] = '送信';
+$lang['registeredUsers'] = '登録ユーザー';
+$lang['onlineUsers'] = 'オンラインユーザー';
+$lang['toggleAutoScroll'] = '自動スクロール on/off';
+$lang['toggleAudio'] = 'サウンド on/off';
+$lang['toggleHelp'] = 'ヘルプ 表示/非表示';
+$lang['toggleSettings'] = '環境設定 表示/非表示';
+$lang['toggleOnlineList'] = 'オンラインリスト 表示/非表示';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Quote';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'フォントカラー';
+$lang['bbCodeTitleBold'] = 'ボールド(太字): [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'イタリック(斜体): [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'アンダーライン: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = '引用: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'コード表示: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'URLリンク: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = '画像: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'フォントカラー: [color=red]text[/color]';
+$lang['help'] = 'ヘルプ';
+$lang['helpItemDescJoin'] = 'チャンネルの変更 :';
+$lang['helpItemCodeJoin'] = '/join チャンネル名';
+$lang['helpItemDescJoinCreate'] = 'プライベートルームへ移動 (登録ユーザーのみ可) :';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'チャンネルへ招待 :';
+$lang['helpItemCodeInvite'] = '/invite ユーザー名';
+$lang['helpItemDescUninvite'] = '招待の取り消し :';
+$lang['helpItemCodeUninvite'] = '/uninvite ユーザー名';
+$lang['helpItemDescLogout'] = 'ログアウト :';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'プライベートメッセージ :';
+$lang['helpItemCodePrivateMessage'] = '/msg ユーザー名';
+$lang['helpItemDescQueryOpen'] = '二人きりモードの開始 :';
+$lang['helpItemCodeQueryOpen'] = '/query ユーザー名';
+$lang['helpItemDescQueryClose'] = '二人きりモードの終了 :';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = '感情を表現する :';
+$lang['helpItemCodeAction'] = '/action スマイリーなど';
+$lang['helpItemDescDescribe'] = '感情を表現する (プライベートメッセージ) :';
+$lang['helpItemCodeDescribe'] = '/describe ユーザー名 スマイリーなど';
+$lang['helpItemDescIgnore'] = 'ユーザーを 無視する/無視しない :';
+$lang['helpItemCodeIgnore'] = '/ignore ユーザー名';
+$lang['helpItemDescIgnoreList'] = '無視ユーザーリスト :';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'ユーザーの居場所 :';
+$lang['helpItemCodeWhereis'] = '/whereis ユーザー名';
+$lang['helpItemDescKick'] = 'ユーザーをキックする (モデレータのみ可) :';
+$lang['helpItemCodeKick'] = '/kick ユーザー名 [アクセス禁止時間(分)]';
+$lang['helpItemDescUnban'] = 'アクセス禁止の解除 (モデレータのみ可) :';
+$lang['helpItemCodeUnban'] = '/unban ユーザー名';
+$lang['helpItemDescBans'] = 'アクセス禁止ユーザーリスト (モデレータのみ可) :';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'ユーザーのIPアドレス (モデレータのみ可) :';
+$lang['helpItemCodeWhois'] = '/whois ユーザー名';
+$lang['helpItemDescWho'] = 'オンラインユーザーリスト :';
+$lang['helpItemCodeWho'] = '/who [チャンネル名]';
+$lang['helpItemDescList'] = '入室可能なチャンネルのリスト :';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'サイコロを振る :';
+$lang['helpItemCodeRoll'] = '/roll [サイコロを振る回数]d[サイコロの面の数]';
+$lang['helpItemDescNick'] = 'ユーザー名の変更 :';
+$lang['helpItemCodeNick'] = '/nick ユーザー名';
+$lang['settings'] = '環境設定';
+$lang['settingsBBCode'] = 'BBCode を有効にする:';
+$lang['settingsBBCodeImages'] = 'BBCode [image] を有効にする :';
+$lang['settingsBBCodeColors'] = 'BBCode [color] を有効にする :';
+$lang['settingsHyperLinks'] = 'ハイパーリンクを有効にする :';
+$lang['settingsLineBreaks'] = '改行を有効にする :';
+$lang['settingsEmoticons'] = 'スマイリーを有効にする :';
+$lang['settingsAutoFocus'] = '自動的にフォーカスをインプットフィールドにセットする :';
+$lang['settingsMaxMessages'] = 'チャットメッセージの最大数 :';
+$lang['settingsWordWrap'] = '長い英数字の折り返しを有効にする :';
+$lang['settingsMaxWordLength'] = '折り返しされない英数字の最大字数 :';
+$lang['settingsDateFormat'] = '日付と表示時間のフォーマット :';
+$lang['settingsPersistFontColor'] = 'フォントカラーを保持する :';
+$lang['settingsAudioVolume'] = 'サウンドのボリューム :';
+$lang['settingsSoundReceive'] = 'サウンド - メッセージの到着 :';
+$lang['settingsSoundSend'] = 'サウンド - メッセージの送信 :';
+$lang['settingsSoundEnter'] = 'サウンド - ログイン、チャンネル入室 :';
+$lang['settingsSoundLeave'] = 'サウンド - ログアウト、チャンネル退室 :';
+$lang['settingsSoundChatBot'] = 'サウンド - チャットボットメッセージ :';
+$lang['settingsSoundError'] = 'サウンド - エラーメッセージ :';
+$lang['settingsBlink'] = '新着メッセージの到着時にウィンドウタイトルを点滅させる :';
+$lang['settingsBlinkInterval'] = '点滅の間隔(ミリ秒) :';
+$lang['settingsBlinkIntervalNumber'] = '点滅の回数 :';
+$lang['playSelectedSound'] = 'サウンドの再生';
+$lang['requiresJavaScript'] = 'このチャットシステムを利用するには JavaScript を有効にする必要があります';
+$lang['errorInvalidUser'] = 'ユーザー名が正しくありません';
+$lang['errorUserInUse'] = 'そのユーザー名は既に使われています';
+$lang['errorBanned'] = 'ユーザー名またはIPアドレスがアクセス禁止されています';
+$lang['errorMaxUsersLoggedIn'] = 'ログインユーザーの最大数に達しているため、これ以上チャットに参加することはできません';
+$lang['errorChatClosed'] = '現在、チャットは停止中です';
+$lang['logsTitle'] = 'AJAX Chat - ログ';
+$lang['logsDate'] = '日時';
+$lang['logsTime'] = '時間';
+$lang['logsSearch'] = '検索';
+$lang['logsPrivateChannels'] = '二人きりモード';
+$lang['logsPrivateMessages'] = 'プライベートメッセージ';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ka.php b/library/ajaxchat/chat/lib/lang/ka.php
new file mode 100644
index 000000000..d92d50886
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ka.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'მეტსახელი';
+$lang['password'] = 'პაროლი';
+$lang['login'] = 'შესვლა';
+$lang['logout'] = 'გასვლა';
+$lang['channel'] = 'არხი';
+$lang['style'] = 'სტილი';
+$lang['language'] = 'ენა';
+$lang['inputLineBreak'] = 'ახალი სტრიქონისთვის დააჭირეთ SHIFT+ENTER';
+$lang['messageSubmit'] = 'დამატება';
+$lang['registeredUsers'] = 'მხოლოდ დარეგისტრირებული წევრები';
+$lang['onlineUsers'] = 'ხაზზე მყოფთა სია';
+$lang['toggleAutoScroll'] = 'ავტოჩამოწევა კი/არა';
+$lang['toggleAudio'] = 'ხმები კი/არა';
+$lang['toggleHelp'] = 'დახმარების ჩვენება/დამალვა';
+$lang['toggleSettings'] = 'პარამეტრების ჩვენება/დამალვა';
+$lang['toggleOnlineList'] = 'ხაზზე მყოფტა სიის ჩვენება/დამალვა';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'ციტატა';
+$lang['bbCodeLabelCode'] = 'კოდი';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'სურათი';
+$lang['bbCodeLabelColor'] = 'შრიფტის ფერი';
+$lang['bbCodeTitleBold'] = 'მსხვილი ტექსტი: [b]ტექსტი[/b]';
+$lang['bbCodeTitleItalic'] = 'დახრილი ტექსტი: [i]ტექსტი[/i]';
+$lang['bbCodeTitleUnderline'] = 'ხაზგასმული ტექსტი: [u]ტექსტი[/u]';
+$lang['bbCodeTitleQuote'] = 'ციტატის ტექსტი: [quote]ტექსტი[/quote] ან [quote=ავტორი]ტექსტი[/quote]';
+$lang['bbCodeTitleCode'] = 'კოდის ჩვენება: [code]კოდი[/code]';
+$lang['bbCodeTitleURL'] = 'URL ბმულის ჩასმა: [url]http://example.org[/url] ან [url=http://example.org]ტექსტი[/url]';
+$lang['bbCodeTitleImg'] = 'ნახატის ჩასმა: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'შრიფტის ფერი: [color=red]ტექსტი[/color]';
+$lang['help'] = 'დახმარება';
+$lang['helpItemDescJoin'] = 'შეუერთდი არხს:';
+$lang['helpItemCodeJoin'] = '/join არხის_სახელი';
+$lang['helpItemDescJoinCreate'] = 'პირადი ოთახის შექმნა (მხოლოდ დარეგისტრირებული წევრები):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'მეგობრის დაპატიჟება (მაგ. პირად ოთახში):';
+$lang['helpItemCodeInvite'] = '/invite მეტსახელი';
+$lang['helpItemDescUninvite'] = 'დაპატიჟების გაუქმება:';
+$lang['helpItemCodeUninvite'] = '/uninvite მეტსახელი';
+$lang['helpItemDescLogout'] = 'ჩატიდან გასვლა:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'პირადი გზავნილი:';
+$lang['helpItemCodePrivateMessage'] = '/msg მეტსახელი ტექსტი';
+$lang['helpItemDescQueryOpen'] = 'გახსენი პირადი არხი:';
+$lang['helpItemCodeQueryOpen'] = '/query მეტსახელი';
+$lang['helpItemDescQueryClose'] = 'დახურე პირადი არხი:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'აღწერე ქმედება:';
+$lang['helpItemCodeAction'] = '/action ტექსტი';
+$lang['helpItemDescDescribe'] = 'აღწერე ქმედება პირად გზავნილში:';
+$lang['helpItemCodeDescribe'] = '/describe მეტსახელი ტექსტი';
+$lang['helpItemDescIgnore'] = 'მიიღე/გააიგნორირე გზავნილები წევრისგან:';
+$lang['helpItemCodeIgnore'] = '/ignore მეტსახელი';
+$lang['helpItemDescIgnoreList'] = 'ჩამოწერე გაიგნორირებული წევრების სია:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'მაჩვენე წევრის არხი:';
+$lang['helpItemCodeWhereis'] = '/whereis მეტსახელი';
+$lang['helpItemDescKick'] = 'ამოარტყი წევრს (მხოლოდ მოდერები):';
+$lang['helpItemCodeKick'] = '/kick მეტსახელი [დაბლოკვის დრო]';
+$lang['helpItemDescUnban'] = 'წევრის ბლოკის მოხსნა (მხოლოდ მოდერები):';
+$lang['helpItemCodeUnban'] = '/unban მეტსახელი';
+$lang['helpItemDescBans'] = 'ჩამოწერე დაბლოკილი წევრების სია (მხოლოდ მოდერები):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'მაჩვენე წევრის IP (მხოლოდ მოდერები):';
+$lang['helpItemCodeWhois'] = '/whois მეტსახელი';
+$lang['helpItemDescWho'] = 'ჩამოწერე ხაზზე მყოფთა სია:';
+$lang['helpItemCodeWho'] = '/who [არხის_სახელი]';
+$lang['helpItemDescList'] = 'ჩამოწერე ხელმისაწვდომი არხები:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'კამათლების გაგორება:';
+$lang['helpItemCodeRoll'] = '/roll [რიცხვი]d[გვერდი]';
+$lang['helpItemDescNick'] = 'მეტსახელის შეცვლა:';
+$lang['helpItemCodeNick'] = '/nick მეტსახელი';
+$lang['settings'] = 'პარამეტრები';
+$lang['settingsBBCode'] = 'ჩართე BBCode:';
+$lang['settingsBBCodeImages'] = 'ჩართე ნახატის BBCode:';
+$lang['settingsBBCodeColors'] = 'ჩართე შრიფტის ფერის BBCode:';
+$lang['settingsHyperLinks'] = 'ჩართე URL ბმულები:';
+$lang['settingsLineBreaks'] = 'ჩართე ახალი სტრიქონის გამოყენება:';
+$lang['settingsEmoticons'] = 'ჩართე სიცილაკები:';
+$lang['settingsAutoFocus'] = 'ტექსტის შეყვანის ველის ავტომატიური ფოკუსირება:';
+$lang['settingsMaxMessages'] = 'ჩატში მყოფი გზავნილების მაქსიმალური რიცხვი:';
+$lang['settingsWordWrap'] = 'გრძელი სიტყვების გადატანა:';
+$lang['settingsMaxWordLength'] = 'სიტყვის მაქსიმალური სიგრძე, სანამ ახალ სტრიქონზე გადავა:';
+$lang['settingsDateFormat'] = 'თარიღისა და დროის ჩვენების ფორმატი:';
+$lang['settingsPersistFontColor'] = 'შრიფტის ფერის შენახვა:';
+$lang['settingsAudioVolume'] = 'ხმის სიმაღლე:';
+$lang['settingsSoundReceive'] = 'შემავალი გზავნილის ხმა:';
+$lang['settingsSoundSend'] = 'გამავალი გზავნილის ხმა:';
+$lang['settingsSoundEnter'] = 'ავტორიზაციისა და არხში შესვლის ხმა:';
+$lang['settingsSoundLeave'] = 'გასვლის და არხის მიტოვების ხმა:';
+$lang['settingsSoundChatBot'] = 'ჩატბოტის გზავნილების ხმა:';
+$lang['settingsSoundError'] = 'შედომის გზავნილების ხმა:';
+$lang['settingsBlink'] = 'ახალ გზავნილზე ფანჯრის დასახელების ციმციმი:';
+$lang['settingsBlinkInterval'] = 'ციმციმის ინტერვალი მილიწამებში:';
+$lang['settingsBlinkIntervalNumber'] = 'ციმციმის ინტერვალების რაოდენობა:';
+$lang['playSelectedSound'] = 'ითამაშე არჩეული ხმა';
+$lang['requiresJavaScript'] = 'ამ ჩატისთვის საჭიროა JavaScript.';
+$lang['errorInvalidUser'] = 'არასწორი მეტსახელი.';
+$lang['errorUserInUse'] = 'მეტსახელი დაკავებულია.';
+$lang['errorBanned'] = 'წევრი ან IP დაბლოკილია.';
+$lang['errorMaxUsersLoggedIn'] = 'ჩატში იმყოფება წევრთა მაქსიმალური შესაძლებელი რიცხვი.';
+$lang['errorChatClosed'] = 'ჩატი ამ წუთისთვის დახურულია.';
+$lang['logsTitle'] = 'AJAX Chat - ჟურნალი';
+$lang['logsDate'] = 'თარიღი';
+$lang['logsTime'] = 'დრო';
+$lang['logsSearch'] = 'ძიება';
+$lang['logsPrivateChannels'] = 'პირადი არხები';
+$lang['logsPrivateMessages'] = 'პირადი გზავნილები';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/kr.php b/library/ajaxchat/chat/lib/lang/kr.php
new file mode 100644
index 000000000..687dd6e30
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/kr.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = '대화명';
+$lang['password'] = '비밀번호';
+$lang['login'] = '로그인';
+$lang['logout'] = '로그아웃';
+$lang['channel'] = '채널';
+$lang['style'] = '스타일';
+$lang['language'] = '언어';
+$lang['inputLineBreak'] = '새 줄을 입력하려면 SHIFT+ENTER를 누르세요';
+$lang['messageSubmit'] = '보내기';
+$lang['registeredUsers'] = '등록된 사용자';
+$lang['onlineUsers'] = '접속중인 사용자';
+$lang['toggleAutoScroll'] = '자동스크롤 on/off';
+$lang['toggleAudio'] = '소리 on/off';
+$lang['toggleHelp'] = '도움말';
+$lang['toggleSettings'] = '설정';
+$lang['toggleOnlineList'] = '접속중인 사용자';
+$lang['bbCodeLabelBold'] = '굵게';
+$lang['bbCodeLabelItalic'] = '이탤릭';
+$lang['bbCodeLabelUnderline'] = '밑줄';
+$lang['bbCodeLabelQuote'] = '따옴표';
+$lang['bbCodeLabelCode'] = '코드';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = '이미지';
+$lang['bbCodeLabelColor'] = '글자색';
+$lang['bbCodeTitleBold'] = '굵게: [b]내용[/b]';
+$lang['bbCodeTitleItalic'] = '이탤릭: [i]내용[/i]';
+$lang['bbCodeTitleUnderline'] = '밑줄: [u]내용[/u]';
+$lang['bbCodeTitleQuote'] = '따옴표: [quote]내용[/quote] 또는 [quote=문자]내용[/quote]';
+$lang['bbCodeTitleCode'] = '코드: [code]코드[/code]';
+$lang['bbCodeTitleURL'] = '주소: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = '이미지: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = '글자색: [color=red]내용[/color]';
+$lang['help'] = '도움말';
+$lang['helpItemDescJoin'] = '채널 접속:';
+$lang['helpItemCodeJoin'] = '/join 채널명';
+$lang['helpItemDescJoinCreate'] = '개인방 생성:';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = '사용자 초대 (예: 개인방으로 초대):';
+$lang['helpItemCodeInvite'] = '/invite 대화명';
+$lang['helpItemDescUninvite'] = '초대 취소:';
+$lang['helpItemCodeUninvite'] = '/uninvite 대화명';
+$lang['helpItemDescLogout'] = '로그아웃';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = '귓속말:';
+$lang['helpItemCodePrivateMessage'] = '/msg 대화명 메시지';
+$lang['helpItemDescQueryOpen'] = '개인방 열기:';
+$lang['helpItemCodeQueryOpen'] = '/query 대화명';
+$lang['helpItemDescQueryClose'] = '개인방 닫기:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = '명령 설명:';
+$lang['helpItemCodeAction'] = '/action 설명내용';
+$lang['helpItemDescDescribe'] = '귓속말로 명령 설명:';
+$lang['helpItemCodeDescribe'] = '/describe 대화명 설명내용';
+$lang['helpItemDescIgnore'] = '대화 차단/허용:';
+$lang['helpItemCodeIgnore'] = '/ignore 대화명';
+$lang['helpItemDescIgnoreList'] = '대화차단 사용자 목록:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = '접속중인 채널 확인:';
+$lang['helpItemCodeWhereis'] = '/whereis 대화명';
+$lang['helpItemDescKick'] = '사용자 추방 (방장 만):';
+$lang['helpItemCodeKick'] = '/kick 대화명 [추방 시간(분)]';
+$lang['helpItemDescUnban'] = '추방 취소 (방장 만):';
+$lang['helpItemCodeUnban'] = '/unban 대화명';
+$lang['helpItemDescBans'] = '추방된 사용자 목록 (방장 만):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = '사용자 접속 IP주소 (방장 만):';
+$lang['helpItemCodeWhois'] = '/whois 대화명';
+$lang['helpItemDescWho'] = '접속중인 사용자 목록:';
+$lang['helpItemCodeWho'] = '/who [채널명]';
+$lang['helpItemDescList'] = '채널목록:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = '주사위 굴리기:';
+$lang['helpItemCodeRoll'] = '/roll [굴린횟수]d[면수]';
+$lang['helpItemDescNick'] = '대화명 변경:';
+$lang['helpItemCodeNick'] = '/nick 대화명';
+$lang['settings'] = '설정';
+$lang['settingsBBCode'] = 'BBCode 사용:';
+$lang['settingsBBCodeImages'] = '이미지 BBCode 사용:';
+$lang['settingsBBCodeColors'] = '글자색 BBCode 사용:';
+$lang['settingsHyperLinks'] = '하이퍼링크 사용:';
+$lang['settingsLineBreaks'] = '엔터키 사용:';
+$lang['settingsEmoticons'] = '이모티콘 사용:';
+$lang['settingsAutoFocus'] = '입력창으로 포커스 자동이동:';
+$lang['settingsMaxMessages'] = '대화창의 최대 메시지 수:';
+$lang['settingsWordWrap'] = '긴 문장 다음줄로 표시:';
+$lang['settingsMaxWordLength'] = '최대 글자수:';
+$lang['settingsDateFormat'] = '날짜, 시간 표시 형식:';
+$lang['settingsPersistFontColor'] = '글자색 고정:';
+$lang['settingsAudioVolume'] = '소리크기:';
+$lang['settingsSoundReceive'] = '메시지 수신 소리:';
+$lang['settingsSoundSend'] = '메시지 송신 소리:';
+$lang['settingsSoundEnter'] = '로그인, 채널 접속 소리:';
+$lang['settingsSoundLeave'] = '로그아웃, 채널 접속해제 소리:';
+$lang['settingsSoundChatBot'] = '시스템 메시지 소리:';
+$lang['settingsSoundError'] = '오류 소리:';
+$lang['settingsBlink'] = '새로운 메시지 도착 시 타이틀 깜빡임:';
+$lang['settingsBlinkInterval'] = '밀리세컨드 단위 깜빡임 속도:';
+$lang['settingsBlinkIntervalNumber'] = '깜빡임 횟수:';
+$lang['playSelectedSound'] = '소리 듣기';
+$lang['requiresJavaScript'] = '이 채팅에는 자바스크립트가 필요합니다.';
+$lang['errorInvalidUser'] = '사용할 수 없는 대화명입니다.';
+$lang['errorUserInUse'] = '사용중인 대화명입니다.';
+$lang['errorBanned'] = '사용자/아이피가 차단되었습니다.';
+$lang['errorMaxUsersLoggedIn'] = '동시에 접속할 수 있는 최대 사용자를 초과했습니다.';
+$lang['errorChatClosed'] = '잠시동안 서비스가 닫혔습니다.';
+$lang['logsTitle'] = 'AJAX Chat - 로그';
+$lang['logsDate'] = '날짜';
+$lang['logsTime'] = '시간';
+$lang['logsSearch'] = '검색';
+$lang['logsPrivateChannels'] = '개인채널';
+$lang['logsPrivateMessages'] = '개인 메시지';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/mk.php b/library/ajaxchat/chat/lib/lang/mk.php
new file mode 100644
index 000000000..f43bcfb7d
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/mk.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Nebojsa Ilijoski
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Име';
+$lang['password'] = 'Лозинка';
+$lang['login'] = 'Влези';
+$lang['logout'] = 'Излези';
+$lang['channel'] = 'Канал';
+$lang['style'] = 'Изглед';
+$lang['language'] = 'Јазик';
+$lang['inputLineBreak'] = 'Притиснете SHIFT+ENTER, за да вметнете нов ред';
+$lang['messageSubmit'] = 'Прашање';
+$lang['registeredUsers'] = 'Регистрирани корисници';
+$lang['onlineUsers'] = 'Online корисници';
+$lang['toggleAutoScroll'] = 'Автопрелистување вкл/иcкл';
+$lang['toggleAudio'] = 'Звук вкл/изкл';
+$lang['toggleHelp'] = 'Покашување/скривање на помошта';
+$lang['toggleSettings'] = 'Покажување/скривање на поставките';
+$lang['toggleOnlineList'] = 'Покажување/скривање на листата со корисници';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Цитат';
+$lang['bbCodeLabelCode'] = 'Код';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Боја на фонт';
+$lang['bbCodeTitleBold'] = 'Задебелен текст: [b]текст[/b]';
+$lang['bbCodeTitleItalic'] = 'Закосен текст: [i]текст[/i]';
+$lang['bbCodeTitleUnderline'] = 'Подцртан текст: [u]текст[/u]';
+$lang['bbCodeTitleQuote'] = 'Цитиран текст: [quote]текст[/quote] или [quote=Автор]текст[/quote]';
+$lang['bbCodeTitleCode'] = 'Покажување на код: [code]код[/code]';
+$lang['bbCodeTitleURL'] = 'URL: [url]http://example.org[/url] или [url=http://example.org]текст[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Боја на заглавие: [color=red]текст[/color]';
+$lang['help'] = 'Помош';
+$lang['helpItemDescJoin'] = 'Присоединување кон канал:';
+$lang['helpItemCodeJoin'] = '/join име_на_канал';
+$lang['helpItemDescJoinCreate'] = 'Креирање сопствена соба (само за регистрирани корисници):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Покана на корисници (напр. во сопствена соба):';
+$lang['helpItemCodeInvite'] = '/invite Корисничко_име';
+$lang['helpItemDescUninvite'] = 'Откажување на покана:';
+$lang['helpItemCodeUninvite'] = '/uninvite Корисничко_име';
+$lang['helpItemDescLogout'] = 'Одјавување од четот:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Лична порака:';
+$lang['helpItemCodePrivateMessage'] = '/msg Корисничко_име Текст';
+$lang['helpItemDescQueryOpen'] = 'Отварање на личен канал:';
+$lang['helpItemCodeQueryOpen'] = '/query Корисничко_име';
+$lang['helpItemDescQueryClose'] = 'Затварање на личен канал:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Опиц на дејство:';
+$lang['helpItemCodeAction'] = '/action Текст';
+$lang['helpItemDescDescribe'] = 'Опис на дејство во приватна порака:';
+$lang['helpItemCodeDescribe'] = '/describe Корисничко_име Текст';
+$lang['helpItemDescIgnore'] = 'Игнорирање/примање на пораки од корисник:';
+$lang['helpItemCodeIgnore'] = '/ignore Корисничко_име';
+$lang['helpItemDescIgnoreList'] = 'Преглед на игнорирани корисници:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Покажување на корисничкиот канал:';
+$lang['helpItemCodeWhereis'] = '/whereis Корисничко_име';
+$lang['helpItemDescKick'] = 'Исфрлање на корисници (само за модератори):';
+$lang['helpItemCodeKick'] = '/kick Корисничко_име [број минути]';
+$lang['helpItemDescUnban'] = 'Одблокирање на корисници (само за модератори):';
+$lang['helpItemCodeUnban'] = '/unban Корисничко_име';
+$lang['helpItemDescBans'] = 'Преглед на блокирани корисници (само за модератори):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Преглед на IP адреса на корисник (само за модератори):';
+$lang['helpItemCodeWhois'] = '/whois Корисничко_име';
+$lang['helpItemDescWho'] = 'Преглед на online корисници:';
+$lang['helpItemCodeWho'] = '/who [Име_на_канал]';
+$lang['helpItemDescList'] = 'Преглед на приватните канали:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Фрлање коцка:';
+$lang['helpItemCodeRoll'] = '/roll [пати]d[страни]';
+$lang['helpItemDescNick'] = 'Промена на корисничкото име:';
+$lang['helpItemCodeNick'] = '/nick Корисничко_име';
+$lang['settings'] = 'Поставки';
+$lang['settingsBBCode'] = 'Користење на BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Користење на на хиперлинк:';
+$lang['settingsLineBreaks'] = 'Користење на крај на ред:';
+$lang['settingsEmoticons'] = 'Користење на емоции:';
+$lang['settingsAutoFocus'] = 'Автоматско фокусирање на полето за внес:';
+$lang['settingsMaxMessages'] = 'Максимален број пораки во прозорецот на четот:';
+$lang['settingsWordWrap'] = 'Префрлање на текст:';
+$lang['settingsMaxWordLength'] = 'Максимална должина на порака пред да биде пренесена:';
+$lang['settingsDateFormat'] = 'Формат на датата и часот:';
+$lang['settingsPersistFontColor'] = 'Постојана боја на фонтот:';
+$lang['settingsAudioVolume'] = 'Гласност на звука:';
+$lang['settingsSoundReceive'] = 'Звук за приемни пораки:';
+$lang['settingsSoundSend'] = 'Звук за испратени пораки:';
+$lang['settingsSoundEnter'] = 'Звук за пораки за влез на четот или на каналот:';
+$lang['settingsSoundLeave'] = 'Звук за пораки за излез од четот или од каналот:';
+$lang['settingsSoundChatBot'] = 'Звук за пораки на чатботот:';
+$lang['settingsSoundError'] = 'Звук за пораки за грешки:';
+$lang['settingsBlink'] = 'Жмигање на заглавието на прозорецот при нови пораки:';
+$lang['settingsBlinkInterval'] = 'Интервал на жмигање во милисекунди:';
+$lang['settingsBlinkIntervalNumber'] = 'Број пати на жмигање:';
+$lang['playSelectedSound'] = 'Преслушување на избраниот звук';
+$lang['requiresJavaScript'] = 'За четот е потребна поддршка на Јаваскрипт.';
+$lang['errorInvalidUser'] = 'Грешно корисничко име.';
+$lang['errorUserInUse'] = 'Корисничкото име е во употреба.';
+$lang['errorBanned'] = 'Корисникот или IP адресата е блокирана.';
+$lang['errorMaxUsersLoggedIn'] = 'Четот го достигна максималниот број на корисници.';
+$lang['errorChatClosed'] = 'Во моментов четот е затворен.';
+$lang['logsTitle'] = 'AJAX Chat — Лого';
+$lang['logsDate'] = 'Дата';
+$lang['logsTime'] = 'Време';
+$lang['logsSearch'] = 'Пребарување';
+$lang['logsPrivateChannels'] = 'Приватни канали';
+$lang['logsPrivateMessages'] = 'Приватни пораки';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/nl-be.php b/library/ajaxchat/chat/lib/lang/nl-be.php
new file mode 100644
index 000000000..db01b9871
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/nl-be.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Nic Mertens
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Gebruikersnaam';
+$lang['password'] = 'Wachtwoord';
+$lang['login'] = 'Inloggen';
+$lang['logout'] = 'Uitloggen';
+$lang['channel'] = 'Kanaal';
+$lang['style'] = 'Stijl';
+$lang['language'] = 'Taal';
+$lang['inputLineBreak'] = 'Typ SHIFT+ENTER om een line break in te geven';
+$lang['messageSubmit'] = 'Verzend';
+$lang['registeredUsers'] = 'Geregistreerde gebruikers';
+$lang['onlineUsers'] = 'Online gebruikers';
+$lang['toggleAutoScroll'] = 'Autoscroll aan/uit';
+$lang['toggleAudio'] = 'Geluid aan/uit';
+$lang['toggleHelp'] = 'Toon/verberg help';
+$lang['toggleSettings'] = 'Toon/verberg instellingen';
+$lang['toggleOnlineList'] = 'Toon/verberg online lijst';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Quote';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Figuur';
+$lang['bbCodeLabelColor'] = 'Kleur lettertype';
+$lang['bbCodeTitleBold'] = 'Tekst in vet: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Tekst in cursief: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Tekst onderlijnd: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Quote tekst: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Code ingeven: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Voeg URL in: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Voeg figuur toe: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Kleur lettertype: [color=red]text[/color]';
+$lang['help'] = 'Help';
+$lang['helpItemDescJoin'] = 'Betreed een kamer:';
+$lang['helpItemCodeJoin'] = '/join Kanaalnaam';
+$lang['helpItemDescJoinCreate'] = 'Maak een privékamer (Enkel geregistreerde gebruikers):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Nodig iemand uit (bv. naar een privékamer):';
+$lang['helpItemCodeInvite'] = '/invite Gebruikersnaam';
+$lang['helpItemDescUninvite'] = 'Annuleer de uitnodiging:';
+$lang['helpItemCodeUninvite'] = '/uninvite Gebruikersnaam';
+$lang['helpItemDescLogout'] = 'Uitloggen:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privé bericht:';
+$lang['helpItemCodePrivateMessage'] = '/msg Gebruikersnaam Tekst';
+$lang['helpItemDescQueryOpen'] = 'Open een privékamer:';
+$lang['helpItemCodeQueryOpen'] = '/query Gebruikersnaam';
+$lang['helpItemDescQueryClose'] = 'Sluit een privékamer:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Beschrijf actie:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Beschrijf actie in privébericht:';
+$lang['helpItemCodeDescribe'] = '/describe Gebruikersnaam Tekst';
+$lang['helpItemDescIgnore'] = 'Negeer/aanvaard berichten van gebruiker:';
+$lang['helpItemCodeIgnore'] = '/ignore Gebruikersnaam';
+$lang['helpItemDescIgnoreList'] = 'Toon de genegeerde gebruikers:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Gebruikersnaam';
+$lang['helpItemDescKick'] = 'Kick een gebruiker (Enkel Moderators of Administrators):';
+$lang['helpItemCodeKick'] = '/kick Gebruikersnaam [aantal minuten]';
+$lang['helpItemDescUnban'] = 'Unban een gebruiker (Enkel Moderators of Administrators):';
+$lang['helpItemCodeUnban'] = '/unban Gebruikersnaam';
+$lang['helpItemDescBans'] = 'Lijst van gebande Gebruikers (Enkel Moderators of Administrators):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Toon gebruikers-IP (Enkel Moderators of Administrators):';
+$lang['helpItemCodeWhois'] = '/whois Gebruikersnaam';
+$lang['helpItemDescWho'] = 'Lijst van gebruikers online:';
+$lang['helpItemCodeWho'] = '/who [Kanaalnaam]';
+$lang['helpItemDescList'] = 'Lijst van beschikbare kanalen:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Werp dobbelsteen:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Wijzig gebruikersnaam:';
+$lang['helpItemCodeNick'] = '/nick Gebruikersnaam';
+$lang['settings'] = 'Instellingen';
+$lang['settingsBBCode'] = 'Inschakelen BBCode:';
+$lang['settingsBBCodeImages'] = 'Inschakelen figuur BBCode:';
+$lang['settingsBBCodeColors'] = 'Inschakelen lettertype kleur BBCode:';
+$lang['settingsHyperLinks'] = 'Inschakelen hyperlinks:';
+$lang['settingsLineBreaks'] = 'Inschakelen line breaks:';
+$lang['settingsEmoticons'] = 'Inschakelen emoticons:';
+$lang['settingsAutoFocus'] = 'Zet automatisch de focus in het invoerveld:';
+$lang['settingsMaxMessages'] = 'Maximaal aantal berichten in de chatkamer:';
+$lang['settingsWordWrap'] = 'Inschakelen wrapping van lange woorden:';
+$lang['settingsMaxWordLength'] = 'Maximale lengte van een woord voor dat het gewrapped wordt:';
+$lang['settingsDateFormat'] = 'Formaat van datum en tijd:';
+$lang['settingsPersistFontColor'] = 'Persiste lettertype kleur:';
+$lang['settingsAudioVolume'] = 'Volume geluid:';
+$lang['settingsSoundReceive'] = 'Geluid voor inkomende berichten:';
+$lang['settingsSoundSend'] = 'Geluid voor buitengaande berichten:';
+$lang['settingsSoundEnter'] = 'Geluid voor login en chatkemer voor binnenkomende berichten:';
+$lang['settingsSoundLeave'] = 'Geluid voor logout en verlaat berichten:';
+$lang['settingsSoundChatBot'] = 'Geluid voor berichten van de bot:';
+$lang['settingsSoundError'] = 'Geluid voor errorberichten:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Speel geselecteerd geluid';
+$lang['requiresJavaScript'] = 'JavaScript is nodig voor deze chat.';
+$lang['errorInvalidUser'] = 'Ongeldige gebruikersnaam.';
+$lang['errorUserInUse'] = 'Gebruikersnaam is in gebruik, kies een andere.';
+$lang['errorBanned'] = 'Gebruiker of gebruikers-IP is gebanned.';
+$lang['errorMaxUsersLoggedIn'] = 'Dit chatkamer heeft het maximum toegelaten aantal ingelogde gebruikers bereikt.';
+$lang['errorChatClosed'] = 'Dit chatkamer is momenteel gesloten.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Tijd';
+$lang['logsSearch'] = 'Zoek';
+$lang['logsPrivateChannels'] = 'Privékanalen';
+$lang['logsPrivateMessages'] = 'Privéberichten';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/nl.php b/library/ajaxchat/chat/lib/lang/nl.php
new file mode 100644
index 000000000..c7dcc4b38
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/nl.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Dutch localisation: Patrick Donker
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Gebruikersnaam';
+$lang['password'] = 'Wachtwoord';
+$lang['login'] = 'Inloggen';
+$lang['logout'] = 'Uitloggen';
+$lang['channel'] = 'Kanaal';
+$lang['style'] = 'Stijl';
+$lang['language'] = 'Taal';
+$lang['inputLineBreak'] = 'Typ SHIFT+ENTER om een line break in te geven';
+$lang['messageSubmit'] = 'Verzend';
+$lang['registeredUsers'] = 'Geregistreerde gebruikers';
+$lang['onlineUsers'] = 'Online gebruikers';
+$lang['toggleAutoScroll'] = 'Autoscroll aan/uit';
+$lang['toggleAudio'] = 'Geluid aan/uit';
+$lang['toggleHelp'] = 'Toon/verberg help';
+$lang['toggleSettings'] = 'Toon/verberg instellingen';
+$lang['toggleOnlineList'] = 'Toon/verberg online lijst';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citeer';
+$lang['bbCodeLabelCode'] = 'Code';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Figuur';
+$lang['bbCodeLabelColor'] = 'Kleur lettertype';
+$lang['bbCodeTitleBold'] = 'Vetgedrukte tekst: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Cursieve tekst: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Onderlijnde tekst: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citeer tekst: [quote]text[/quote] of [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Code ingeven: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Voeg URL in: [url]http://example.org[/url] of [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Voeg figuur toe: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Kleur lettertype: [color=red]text[/color]';
+$lang['help'] = 'Help';
+$lang['helpItemDescJoin'] = 'Betreed een kanaal:';
+$lang['helpItemCodeJoin'] = '/join Kanaalnaam';
+$lang['helpItemDescJoinCreate'] = 'Maak een privékamer (Enkel geregistreerde gebruikers):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Nodig iemand uit (voor bijv. een privékamer):';
+$lang['helpItemCodeInvite'] = '/invite Gebruikersnaam';
+$lang['helpItemDescUninvite'] = 'Annuleer uitnodiging:';
+$lang['helpItemCodeUninvite'] = '/uninvite Gebruikersnaam';
+$lang['helpItemDescLogout'] = 'Uitloggen:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privé bericht:';
+$lang['helpItemCodePrivateMessage'] = '/msg Gebruikersnaam Tekst';
+$lang['helpItemDescQueryOpen'] = 'Open een privékamer:';
+$lang['helpItemCodeQueryOpen'] = '/query Gebruikersnaam';
+$lang['helpItemDescQueryClose'] = 'Sluit een privékamer:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Beschrijf actie:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Beschrijf actie in privébericht:';
+$lang['helpItemCodeDescribe'] = '/describe Gebruikersnaam Tekst';
+$lang['helpItemDescIgnore'] = 'Negeer/aanvaard berichten van gebruiker:';
+$lang['helpItemCodeIgnore'] = '/ignore Gebruikersnaam';
+$lang['helpItemDescIgnoreList'] = 'Toon genegeerde gebruikers:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Waar bevindt zich een gebruiker:';
+$lang['helpItemCodeWhereis'] = '/whereis Gebruikersnaam';
+$lang['helpItemDescKick'] = 'Verwijder een gebruiker (Enkel Moderators of Administrators):';
+$lang['helpItemCodeKick'] = '/kick Gebruikersnaam [aantal minuten]';
+$lang['helpItemDescUnban'] = 'Hertoelaten van een gebruiker (Enkel Moderators of Administrators):';
+$lang['helpItemCodeUnban'] = '/unban Gebruikersnaam';
+$lang['helpItemDescBans'] = 'Lijst van verbannen Gebruikers (Enkel Moderators of Administrators):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Toon IP adres gebruikers (Enkel Moderators of Administrators):';
+$lang['helpItemCodeWhois'] = '/whois Gebruikersnaam';
+$lang['helpItemDescWho'] = 'Lijst van online gebruikers:';
+$lang['helpItemCodeWho'] = '/who [Kanaalnaam]';
+$lang['helpItemDescList'] = 'Lijst van beschikbare kanalen:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Gooi dobbelsteen:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Wijzig gebruikersnaam:';
+$lang['helpItemCodeNick'] = '/nick Gebruikersnaam';
+$lang['settings'] = 'Instellingen';
+$lang['settingsBBCode'] = 'Inschakelen BBCode:';
+$lang['settingsBBCodeImages'] = 'Inschakelen figuur BBCode:';
+$lang['settingsBBCodeColors'] = 'Inschakelen lettertype kleur BBCode:';
+$lang['settingsHyperLinks'] = 'Inschakelen hyperlinks:';
+$lang['settingsLineBreaks'] = 'Inschakelen line breaks:';
+$lang['settingsEmoticons'] = 'Inschakelen emoticons:';
+$lang['settingsAutoFocus'] = 'Zet automatisch de focus op het invoerveld:';
+$lang['settingsMaxMessages'] = 'Maximaal aantal berichten in de chatkamer:';
+$lang['settingsWordWrap'] = 'Inschakelen afbreken van lange woorden:';
+$lang['settingsMaxWordLength'] = 'Maximale lengte van een woord alvorens het afgebroken wordt:';
+$lang['settingsDateFormat'] = 'Formaat van datum en tijd:';
+$lang['settingsPersistFontColor'] = 'Vaste kleur lettertype:';
+$lang['settingsAudioVolume'] = 'Volume geluid:';
+$lang['settingsSoundReceive'] = 'Geluid bij binnenkomende berichten:';
+$lang['settingsSoundSend'] = 'Geluid bij buitengaande berichten:';
+$lang['settingsSoundEnter'] = 'Geluid bij login en betreden van chat';
+$lang['settingsSoundLeave'] = 'Geluid bij logout en verlaten chat:';
+$lang['settingsSoundChatBot'] = 'Geluid bij systeenberichten:';
+$lang['settingsSoundError'] = 'Geluid bij foutmeldingen:';
+$lang['settingsBlink'] = 'Knipper tekst windowtitel bij nieuw bericht:';
+$lang['settingsBlinkInterval'] = 'Knipperinterval in milliseconden:';
+$lang['settingsBlinkIntervalNumber'] = 'Aantal keren knippering van tekst:';
+$lang['playSelectedSound'] = 'Speel geselecteerd geluid af';
+$lang['requiresJavaScript'] = 'JavaScript is vereist voor deze chat.';
+$lang['errorInvalidUser'] = 'Ongeldige gebruikersnaam.';
+$lang['errorUserInUse'] = 'Gebruikersnaam is in gebruik, kies een andere.';
+$lang['errorBanned'] = 'Gebruiker of gebruikers-IP is verbannen.';
+$lang['errorMaxUsersLoggedIn'] = 'Deze chatkamer heeft het maximum aantal toegelaten gebruikers bereikt.';
+$lang['errorChatClosed'] = 'Deze chatkamer is momenteel gesloten.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Tijd';
+$lang['logsSearch'] = 'Zoek';
+$lang['logsPrivateChannels'] = 'Privékanalen';
+$lang['logsPrivateMessages'] = 'Privéberichten';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/no.php b/library/ajaxchat/chat/lib/lang/no.php
new file mode 100644
index 000000000..52fe4afbe
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/no.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author DagArneKirkerod
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Brukernavn';
+$lang['password'] = 'Passord';
+$lang['login'] = 'Logg inn';
+$lang['logout'] = 'Logg ut';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Språk';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'Send';
+$lang['registeredUsers'] = 'Registrerte Brukere';
+$lang['onlineUsers'] = 'Påloggede brukere';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Siter';
+$lang['bbCodeLabelCode'] = 'Kode';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Tekst Farge';
+$lang['bbCodeTitleBold'] = 'Fet tekst: [b]tekst[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursiv tekst: [i]tekst[/i]';
+$lang['bbCodeTitleUnderline'] = 'Understrek tekst: [u]tekst[/u]';
+$lang['bbCodeTitleQuote'] = 'Siter tekst: [quote]tekst[/quote] or [quote=author]tekst[/quote]';
+$lang['bbCodeTitleCode'] = 'Vis kode: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Legg til url: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Tekst farge: [color=red]text[/color]';
+$lang['help'] = 'Hjelp';
+$lang['helpItemDescJoin'] = 'Delta i en kanal:';
+$lang['helpItemCodeJoin'] = '/Join kanalnavn';
+$lang['helpItemDescJoinCreate'] = 'Lag et privat rom (Bare Registrerte Brukere):';
+$lang['helpItemCodeJoinCreate'] = '/Join';
+$lang['helpItemDescInvite'] = 'Inviter noen (for eksempel til et privat rom):';
+$lang['helpItemCodeInvite'] = '/invite brukernavn';
+$lang['helpItemDescUninvite'] = 'Opphev invitasjon:';
+$lang['helpItemCodeUninvite'] = '/uninvite brukernavn';
+$lang['helpItemDescLogout'] = 'Logg ut fra Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privat melding:';
+$lang['helpItemCodePrivateMessage'] = '/msg brukernavn tekst';
+$lang['helpItemDescQueryOpen'] = 'Åpne en privat kanal:';
+$lang['helpItemCodeQueryOpen'] = '/query brukernavn';
+$lang['helpItemDescQueryClose'] = 'Lukk en privat kanal:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Beskriv handling:';
+$lang['helpItemCodeAction'] = '/action tekst';
+$lang['helpItemDescDescribe'] = 'Beskriv handling i privat melding:';
+$lang['helpItemCodeDescribe'] = '/describe brukernavn tekst';
+$lang['helpItemDescIgnore'] = 'Ignorer/aksepter meldinger fra bruker:';
+$lang['helpItemCodeIgnore'] = '/ignore brukernavn';
+$lang['helpItemDescIgnoreList'] = 'Liste med ignorerte brukere:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Spark ut en bruker (bare Moderatorer):';
+$lang['helpItemCodeKick'] = '/kick brukernavn [minutter]';
+$lang['helpItemDescUnban'] = 'Ta inn en utsparket bruker (bare Moderatorer):';
+$lang['helpItemCodeUnban'] = '/unban brukernavn';
+$lang['helpItemDescBans'] = 'Liste med utsparkede brukere (bare Moderatorer):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Vis bruker IP (bare Moderatorer):';
+$lang['helpItemCodeWhois'] = '/whois brukernavn';
+$lang['helpItemDescWho'] = 'Vis påloggede brukere:';
+$lang['helpItemCodeWho'] = '/who [kanalnavn]';
+$lang['helpItemDescList'] = 'Vis tilgjenglige kanaler:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Rull terning:';
+$lang['helpItemCodeRoll'] = '/roll [nummer]d[sider]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'JavaScript trengs for denne chat.';
+$lang['errorInvalidUser'] = 'Ugyldig brukernavn.';
+$lang['errorUserInUse'] = 'Brukernavn er i bruk.';
+$lang['errorBanned'] = 'Bruker eller IP er utsparket.';
+$lang['errorMaxUsersLoggedIn'] = 'Chatten har nådd maksimalt antall innloggede brukere.';
+$lang['errorChatClosed'] = 'Chatten er for øyeblikket stengt .';
+$lang['logsTitle'] = 'AJAX Chat - Logger';
+$lang['logsDate'] = 'Dato';
+$lang['logsTime'] = 'Tid';
+$lang['logsSearch'] = 'Søk';
+$lang['logsPrivateChannels'] = 'Private Kanaler';
+$lang['logsPrivateMessages'] = 'Private Meldinger';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/pl.php b/library/ajaxchat/chat/lib/lang/pl.php
new file mode 100644
index 000000000..92a1716a6
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/pl.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Tomasz Topa, http://tomasz.topa.pl/
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Nick';
+$lang['password'] = 'Hasło';
+$lang['login'] = 'Zaloguj';
+$lang['logout'] = 'Wyloguj';
+$lang['channel'] = 'Pokój';
+$lang['style'] = 'Styl';
+$lang['language'] = 'Język';
+$lang['inputLineBreak'] = 'Wciśnij SHIFT+ENTER aby przejść do nowej linijki';
+$lang['messageSubmit'] = 'Wyślij';
+$lang['registeredUsers'] = 'Zarejestrowani użytkownicy';
+$lang['onlineUsers'] = 'Użytkownicy online';
+$lang['toggleAutoScroll'] = 'Automatyczne przewijanie wł/wył';
+$lang['toggleAudio'] = 'Dźwięk wł/wył';
+$lang['toggleHelp'] = 'Pokaż/ukryj pomoc';
+$lang['toggleSettings'] = 'Pokaż/ukryj ustawienia';
+$lang['toggleOnlineList'] = 'Pokaż/ukryj listę osób online';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Cytat';
+$lang['bbCodeLabelCode'] = 'Kod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Kolor tekstu';
+$lang['bbCodeTitleBold'] = 'Pogrubiony: [b]tekst[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursywa: [i]tekst[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podkreślony: [u]tekst[/u]';
+$lang['bbCodeTitleQuote'] = 'Cytat: [quote]tekst[/quote] lub [quote=autor]tekst[/quote]';
+$lang['bbCodeTitleCode'] = 'Kod: [code]kod[/code]';
+$lang['bbCodeTitleURL'] = 'Wstaw adres: [url]http://example.org[/url] lub [url=http://example.org]opis[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Kolor tekstu: [color=red]tekst[/color]';
+$lang['help'] = 'Pomoc';
+$lang['helpItemDescJoin'] = 'Wejdź do pokoju:';
+$lang['helpItemCodeJoin'] = '/join NazwaPokoju';
+$lang['helpItemDescJoinCreate'] = 'Utwórz nowy pokój (Tylko dla zarejestrowanych):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Zaproś kogoś (np. do prywatnego pokoju):';
+$lang['helpItemCodeInvite'] = '/invite Nick';
+$lang['helpItemDescUninvite'] = 'Odwołaj zaproszenie:';
+$lang['helpItemCodeUninvite'] = '/uninvite Nick';
+$lang['helpItemDescLogout'] = 'Wyloguj z czata:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Prywatna wiadomość:';
+$lang['helpItemCodePrivateMessage'] = '/msg Nick tekst';
+$lang['helpItemDescQueryOpen'] = 'Prywatna rozmowa:';
+$lang['helpItemCodeQueryOpen'] = '/query Nick';
+$lang['helpItemDescQueryClose'] = 'Zakończ prywatną rozmowę:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Napisz co teraz robisz:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Napisz komuś co teraz robisz:';
+$lang['helpItemCodeDescribe'] = '/describe Nick Tekst';
+$lang['helpItemDescIgnore'] = 'Ignoruj/akceptuj wiadomości od użytkownika:';
+$lang['helpItemCodeIgnore'] = '/ignore Nick';
+$lang['helpItemDescIgnoreList'] = 'Lista ignorowanych:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Gdzie jest użytkownik:';
+$lang['helpItemCodeWhereis'] = '/whereis Nick';
+$lang['helpItemDescKick'] = 'Wyrzuć użytkownika (Tylko dla moderatorów):';
+$lang['helpItemCodeKick'] = '/kick Nick [Czas zablokowania w minutach]';
+$lang['helpItemDescUnban'] = 'Odblokuj użytkowników (Tylko dla moderatorów):';
+$lang['helpItemCodeUnban'] = '/unban Nick';
+$lang['helpItemDescBans'] = 'Lista zablokowanych użytkowników (Tylko dla moderatorów):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Pokaż IP użytkownika (Tylko dla moderatorów):';
+$lang['helpItemCodeWhois'] = '/whois Nick';
+$lang['helpItemDescWho'] = 'Lista użytkowników online:';
+$lang['helpItemCodeWho'] = '/who [NazwaPokoju]';
+$lang['helpItemDescList'] = 'Lista pokoi:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Rzuć kostką:';
+$lang['helpItemCodeRoll'] = '/roll [ile_razy]d[ilu_ścienną]';
+$lang['helpItemDescNick'] = 'Zmień nick:';
+$lang['helpItemCodeNick'] = '/nick Nick';
+$lang['settings'] = 'Ustawienia';
+$lang['settingsBBCode'] = 'Pozwól na BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Pozwól na linki:';
+$lang['settingsLineBreaks'] = 'Pozwól na używanie wielu linijek:';
+$lang['settingsEmoticons'] = 'Pozwól na emotikonki:';
+$lang['settingsAutoFocus'] = 'Automatycznie ustawiaj kursor w polu tekstowym:';
+$lang['settingsMaxMessages'] = 'Maksymalna liczba wiadomości w głównym oknie:';
+$lang['settingsWordWrap'] = 'Pozwól dzielić długie wyrazy:';
+$lang['settingsMaxWordLength'] = 'Maksymalna długość wyrazu, którego nie wolno dzielić:';
+$lang['settingsDateFormat'] = 'Format wyświetlanej daty i czasu:';
+$lang['settingsPersistFontColor'] = 'Nie pozwól na zmianę koloru tekstu:';
+$lang['settingsAudioVolume'] = 'Głośność:';
+$lang['settingsSoundReceive'] = 'Dźwięk dla przychodzących wiadomości:';
+$lang['settingsSoundSend'] = 'Dźwięk dla wysyłanych wiadomości:';
+$lang['settingsSoundEnter'] = 'Dźwięk dla wejść do pokoju:';
+$lang['settingsSoundLeave'] = 'Dźwięk dla wyjść z pokoju:';
+$lang['settingsSoundChatBot'] = 'Dźwięk dla informacji od bota:';
+$lang['settingsSoundError'] = 'Dźwięk dla informacji o błędach:';
+$lang['settingsBlink'] = 'Miganie okienka przy nadejściu nowej wiadomości:';
+$lang['settingsBlinkInterval'] = 'Odstęp pomiędzy mignięciami (w milisekundach):';
+$lang['settingsBlinkIntervalNumber'] = 'Liczba mignięć:';
+$lang['playSelectedSound'] = 'Odtwórz wybrany dźwięk';
+$lang['requiresJavaScript'] = 'Do poprawnego działania czata wymagana jest obsługa JavaScript.';
+$lang['errorInvalidUser'] = 'Nieprawidłowy nick.';
+$lang['errorUserInUse'] = 'Wybrany nick jest już używany.';
+$lang['errorBanned'] = 'Nick lub IP jest zablokowane.';
+$lang['errorMaxUsersLoggedIn'] = 'Czat jest już pełny.';
+$lang['errorChatClosed'] = 'Czat jest tymczasowo wyłączony.';
+$lang['logsTitle'] = 'AJAX Chat - Logi';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Czas';
+$lang['logsSearch'] = 'Szukaj';
+$lang['logsPrivateChannels'] = 'Prywatne pokoje';
+$lang['logsPrivateMessages'] = 'Prywatne wiadomości';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/pt-br.php b/library/ajaxchat/chat/lib/lang/pt-br.php
new file mode 100644
index 000000000..034a5fb09
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/pt-br.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Pedro Innecco
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Usuário';
+$lang['password'] = 'Senha';
+$lang['login'] = 'Entrar';
+$lang['logout'] = 'Sair';
+$lang['channel'] = 'Canal';
+$lang['style'] = 'Aparência';
+$lang['language'] = 'Idioma';
+$lang['inputLineBreak'] = 'Pressione SHIFT+ENTER para inserir uma quebra de linha';
+$lang['messageSubmit'] = 'Enviar';
+$lang['registeredUsers'] = 'Para Usuários Registrados';
+$lang['onlineUsers'] = 'Usuários Online';
+$lang['toggleAutoScroll'] = 'Autorolagem liga/desliga';
+$lang['toggleAudio'] = 'Som liga/desliga';
+$lang['toggleHelp'] = 'Mostrar/esconder ajuda';
+$lang['toggleSettings'] = 'Mostrar/esconder configurações';
+$lang['toggleOnlineList'] = 'Mostrar/esconder lista de usuários online';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citar';
+$lang['bbCodeLabelCode'] = 'Código';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Imagem';
+$lang['bbCodeLabelColor'] = 'Cor da fonte';
+$lang['bbCodeTitleBold'] = 'Texto negrito: [b]texto[/b]';
+$lang['bbCodeTitleItalic'] = 'Texto itálico: [i]texto[/i]';
+$lang['bbCodeTitleUnderline'] = 'Texto sublinhado: [u]texto[/u]';
+$lang['bbCodeTitleQuote'] = 'Citar texto: [quote]texto[/quote] ou [quote=autor]texto[/quote]';
+$lang['bbCodeTitleCode'] = 'Citar código: [code]código[/code]';
+$lang['bbCodeTitleURL'] = 'Inserir URL: [url]http://example.org[/url] or [url=http://example.org]texto[/url]';
+$lang['bbCodeTitleImg'] = 'Inserir imagem: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Cor da fonte: [color=red]texto[/color]';
+$lang['help'] = 'Ajuda';
+$lang['helpItemDescJoin'] = 'Entrar em um canal:';
+$lang['helpItemCodeJoin'] = '/join Nome do Canal';
+$lang['helpItemDescJoinCreate'] = 'Criar uma sala privada (Somente usuários registrados):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Convidar alguém (Por exemplo, para uma sala privada):';
+$lang['helpItemCodeInvite'] = '/invite Usuário';
+$lang['helpItemDescUninvite'] = 'Cancelar convite';
+$lang['helpItemCodeUninvite'] = '/uninvite Usuário';
+$lang['helpItemDescLogout'] = 'Sair do Chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Enviar mensagem privada:';
+$lang['helpItemCodePrivateMessage'] = '/msg Usuário Texto';
+$lang['helpItemDescQueryOpen'] = 'Abrir um canal privado:';
+$lang['helpItemCodeQueryOpen'] = '/query Usuário';
+$lang['helpItemDescQueryClose'] = 'Fechar um canal privado:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Descrever uma ação:';
+$lang['helpItemCodeAction'] = '/action Texto';
+$lang['helpItemDescDescribe'] = 'Descrever uma ação em uma mensagem privada:';
+$lang['helpItemCodeDescribe'] = '/describe Usuário Texto';
+$lang['helpItemDescIgnore'] = 'Ignorar/Aceitar mensagens de um usuário:';
+$lang['helpItemCodeIgnore'] = '/ignore Usuário';
+$lang['helpItemDescIgnoreList'] = 'Listar usuários ignorados:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Exibir canal de um usuário:';
+$lang['helpItemCodeWhereis'] = '/whereis Usuário';
+$lang['helpItemDescKick'] = 'Banir um usuário (Somente Moderadores):';
+$lang['helpItemCodeKick'] = '/kick Usuário [Bandido por minutos]';
+$lang['helpItemDescUnban'] = 'Desbanir um usuário (Somente Moderadores):';
+$lang['helpItemCodeUnban'] = '/unban Usuário';
+$lang['helpItemDescBans'] = 'Listar usuários banidos (Somente Moderadores):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Exibir IP de um usuário (Somente Moderadores):';
+$lang['helpItemCodeWhois'] = '/whois Usuário';
+$lang['helpItemDescWho'] = 'Listar usuários online:';
+$lang['helpItemCodeWho'] = '/who [Channelname]';
+$lang['helpItemDescList'] = 'Listar canais diponíveis:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Jogar dados:';
+$lang['helpItemCodeRoll'] = '/roll [números]d[lados]';
+$lang['helpItemDescNick'] = 'Trocar seu nome de usuário:';
+$lang['helpItemCodeNick'] = '/nick Nome';
+$lang['settings'] = 'Configurações';
+$lang['settingsBBCode'] = 'Permitir BBCode:';
+$lang['settingsBBCodeImages'] = 'Permitir BBCode image (imagem):';
+$lang['settingsBBCodeColors'] = 'Permitir BBCode font color (cor de fonte):';
+$lang['settingsHyperLinks'] = 'Permitir hyperlinks:';
+$lang['settingsLineBreaks'] = 'Permitir quebra-linha:';
+$lang['settingsEmoticons'] = 'Permitir emoticons:';
+$lang['settingsAutoFocus'] = 'Definir automaticamente o foco no campo de envio de mensagens:';
+$lang['settingsMaxMessages'] = 'O número máximo de mensagens na lista do Chat:';
+$lang['settingsWordWrap'] = 'Permitir quebra de linha para palavras longas:';
+$lang['settingsMaxWordLength'] = 'O comprimento máximo de uma palavra antes dele começa envolvido:';
+$lang['settingsDateFormat'] = 'Formato da exposição da data e da hora:';
+$lang['settingsPersistFontColor'] = 'Persistir cor da fonte:';
+$lang['settingsAudioVolume'] = 'Volume do som:';
+$lang['settingsSoundReceive'] = 'Som para mensagens recebidas:';
+$lang['settingsSoundSend'] = 'Som para mensagens enviadas:';
+$lang['settingsSoundEnter'] = 'Som para login e avisos de entrada em canais:';
+$lang['settingsSoundLeave'] = 'Som para logout e avisos de saida em canais:';
+$lang['settingsSoundChatBot'] = 'Som para mensagens do chatbot:';
+$lang['settingsSoundError'] = 'Som para mensagens de erro:';
+$lang['settingsBlink'] = 'Título da janela do piscamento em mensagens novas:';
+$lang['settingsBlinkInterval'] = 'Intervalo do piscamento nos milissegundos:';
+$lang['settingsBlinkIntervalNumber'] = 'Número de intervalos do piscamento:';
+$lang['playSelectedSound'] = 'Reproduzir som selecionado';
+$lang['requiresJavaScript'] = 'Javascript é requerido para este Chat.';
+$lang['errorInvalidUser'] = 'Usuário inválido.';
+$lang['errorUserInUse'] = 'Usuário já se encontra em uso.';
+$lang['errorBanned'] = 'O usuário ou endereço de IP foi banido do chat.';
+$lang['errorMaxUsersLoggedIn'] = 'O chat atingiu o número máximo de usuários permitidos.';
+$lang['errorChatClosed'] = 'O chat está fechado no momento.';
+$lang['logsTitle'] = 'Ajax Chat - Relatório';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Hora';
+$lang['logsSearch'] = 'Pesquisar';
+$lang['logsPrivateChannels'] = 'Canais privados';
+$lang['logsPrivateMessages'] = 'Mensagens privadas';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/pt-pt.php b/library/ajaxchat/chat/lib/lang/pt-pt.php
new file mode 100644
index 000000000..e3399eb04
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/pt-pt.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author of translate Carlos Rocha (aka Broas@)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Nick';
+$lang['password'] = 'Password';
+$lang['login'] = 'Entrar';
+$lang['logout'] = 'Sair';
+$lang['channel'] = 'Sala';
+$lang['style'] = 'Aparência';
+$lang['language'] = 'Idioma';
+$lang['inputLineBreak'] = 'Prima SHIFT+ENTER para inserir uma quebra de linha';
+$lang['messageSubmit'] = 'Enviar';
+$lang['registeredUsers'] = 'Utilizadores registados';
+$lang['onlineUsers'] = 'Utilizadores online';
+$lang['toggleAutoScroll'] = 'Ligar/Desligar scroll automático';
+$lang['toggleAudio'] = 'Ligar/Desligar som';
+$lang['toggleHelp'] = 'Mostrar/Esconder ajuda';
+$lang['toggleSettings'] = 'Mostrar/Esconder configurações';
+$lang['toggleOnlineList'] = 'Mostrar/Esconder listas online';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citar';
+$lang['bbCodeLabelCode'] = 'Código';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Imagem';
+$lang['bbCodeLabelColor'] = 'Cor da fonte';
+$lang['bbCodeTitleBold'] = 'Texto a negrito: [b]texto[/b]';
+$lang['bbCodeTitleItalic'] = 'Texto itálico: [i]texto[/i]';
+$lang['bbCodeTitleUnderline'] = 'Texto sublinhado: [u]texto[/u]';
+$lang['bbCodeTitleQuote'] = 'Citar texto: [quote]texto[/quote] ou [quote=autor]texto[/quote]';
+$lang['bbCodeTitleCode'] = 'Citar código: [code]código[/code]';
+$lang['bbCodeTitleURL'] = 'Inserir URL: [url]http://example.org[/url] ou [url=http://example.org]texto[/url]';
+$lang['bbCodeTitleImg'] = 'Inserir imagem: [img]http://example.org/imagem.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Cor da fonte: [color=red]texto[/color]';
+$lang['help'] = 'Ajuda';
+$lang['helpItemDescJoin'] = 'Entrar numa sala:';
+$lang['helpItemCodeJoin'] = '/join [Nome da sala]';
+$lang['helpItemDescJoinCreate'] = 'Criar sala privada (Só para utilizadores registados):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Convidar alguém para uma sala privada:';
+$lang['helpItemCodeInvite'] = '/invite [Utilizador]';
+$lang['helpItemDescUninvite'] = 'Cancelar convite';
+$lang['helpItemCodeUninvite'] = '/uninvite [Utilizador]';
+$lang['helpItemDescLogout'] = 'Sair do chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Enviar mensagem privada:';
+$lang['helpItemCodePrivateMessage'] = '/msg [Utilizador] [Texto]';
+$lang['helpItemDescQueryOpen'] = 'Abrir uma sala privada:';
+$lang['helpItemCodeQueryOpen'] = '/query [Utilizador]';
+$lang['helpItemDescQueryClose'] = 'Fechar uma sala privada:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Acção:';
+$lang['helpItemCodeAction'] = '/action [Texto]';
+$lang['helpItemDescDescribe'] = 'Descreve a acção em mensagem privada:';
+$lang['helpItemCodeDescribe'] = '/describe [Utilizador] [Texto]';
+$lang['helpItemDescIgnore'] = 'Adicionar/Remover utilizador à lista de ignorados:';
+$lang['helpItemCodeIgnore'] = '/ignore [Utilizador]';
+$lang['helpItemDescIgnoreList'] = 'Lista de utilizadores ignorados:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Encontrar um utilizador:';
+$lang['helpItemCodeWhereis'] = '/whereis [Utilizador]';
+$lang['helpItemDescKick'] = 'Kickar um utilizador (Só Moderadores):';
+$lang['helpItemCodeKick'] = '/kick [Utilizador] [Minutos]';
+$lang['helpItemDescUnban'] = 'Desbanir um utilizador (Só Moderadores):';
+$lang['helpItemCodeUnban'] = '/unban [Utilizador]';
+$lang['helpItemDescBans'] = 'Lista de utilizadores banidos (Só Moderadores):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Mostrar IP de um utilizador (Só Moderadores):';
+$lang['helpItemCodeWhois'] = '/whois [Utilizador]';
+$lang['helpItemDescWho'] = 'Lista de utilizadores online na sala:';
+$lang['helpItemCodeWho'] = '/who ou /who [Sala]';
+$lang['helpItemDescList'] = 'Lista canais diponíveis:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Jogar dados:';
+$lang['helpItemCodeRoll'] = '/roll [números] [dados]';
+$lang['helpItemDescNick'] = 'Trocar de nick:';
+$lang['helpItemCodeNick'] = '/nick [Novo nick]';
+$lang['settings'] = 'Configurações';
+$lang['settingsBBCode'] = 'Permitir BBCode:';
+$lang['settingsBBCodeImages'] = 'Permitir BBCode para imagem:';
+$lang['settingsBBCodeColors'] = 'Permitir BBCode para cor da fonte:';
+$lang['settingsHyperLinks'] = 'Permitir URL:';
+$lang['settingsLineBreaks'] = 'Permitir quebra de linha:';
+$lang['settingsEmoticons'] = 'Permitir smileys:';
+$lang['settingsAutoFocus'] = 'Definir automaticamente a centrar-se no campo de pesquisa:';
+$lang['settingsMaxMessages'] = 'Número máximo de mensagens no Chat:';
+$lang['settingsWordWrap'] = 'Permitir palavras longas:';
+$lang['settingsMaxWordLength'] = 'O comprimento máximo de uma palavra é de:';
+$lang['settingsDateFormat'] = 'Formato da hora e data:';
+$lang['settingsPersistFontColor'] = 'Persistir cor da fonte:';
+$lang['settingsAudioVolume'] = 'Volume do som:';
+$lang['settingsSoundReceive'] = 'Som para as mensagens recebidas:';
+$lang['settingsSoundSend'] = 'Som de mensagens enviadas:';
+$lang['settingsSoundEnter'] = 'Som de login:';
+$lang['settingsSoundLeave'] = 'Som de logout:';
+$lang['settingsSoundChatBot'] = 'Som para mensagens do chatbot:';
+$lang['settingsSoundError'] = 'Som para mensagens de erro:';
+$lang['settingsBlink'] = 'Título da janela do "piscamento" em mensagens novas:';
+$lang['settingsBlinkInterval'] = 'Intervalo do "piscamento" em milissegundos:';
+$lang['settingsBlinkIntervalNumber'] = 'Número de intervalos do "piscamento":';
+$lang['playSelectedSound'] = 'Reproduzir o som selecionado';
+$lang['requiresJavaScript'] = 'O Javascript tem de estar ligado para entrares no Chat.';
+$lang['errorInvalidUser'] = 'Nick inválido.';
+$lang['errorUserInUse'] = 'Nick em uso.';
+$lang['errorBanned'] = 'O teu nick ou IP está banido.';
+$lang['errorMaxUsersLoggedIn'] = 'O chat atingiu o número máximo de utilizadores ligados.';
+$lang['errorChatClosed'] = 'O Chat está encerrado de momento.';
+$lang['logsTitle'] = 'AJAX Chat - Relatório';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Tempo';
+$lang['logsSearch'] = 'Procurar';
+$lang['logsPrivateChannels'] = 'Salas privadas';
+$lang['logsPrivateMessages'] = 'Mensagens privadas';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ro.php b/library/ajaxchat/chat/lib/lang/ro.php
new file mode 100644
index 000000000..8e6d6418f
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ro.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author K.Z.
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'Chat AJAX';
+$lang['userName'] = 'Nume de utilizator';
+$lang['password'] = 'Parolă';
+$lang['login'] = 'Autentificare';
+$lang['logout'] = 'Ieşire';
+$lang['channel'] = 'Canal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Limbă';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'Trimite';
+$lang['registeredUsers'] = 'Utizatori înregistraţi';
+$lang['onlineUsers'] = 'Utilizatori activi';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citat';
+$lang['bbCodeLabelCode'] = 'Cod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Culoare fontului';
+$lang['bbCodeTitleBold'] = 'Text îngroşat: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Text înclinat: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Text subliniat: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citează text: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Scrie cod: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Introdu URL: [url]http://example.org[/url] or [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Culoarea fontului: [color=red]text[/color]';
+$lang['help'] = 'Ajutor';
+$lang['helpItemDescJoin'] = 'Alăturăte canalului:';
+$lang['helpItemCodeJoin'] = '/join Channelname';
+$lang['helpItemDescJoinCreate'] = 'Creează o cameră privată de chat (Utilizatorii înregistraţi):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Invită pe cineva (ex.: într-o cameră privată):';
+$lang['helpItemCodeInvite'] = '/invite Username';
+$lang['helpItemDescUninvite'] = 'Respinge invitaţia:';
+$lang['helpItemCodeUninvite'] = '/uninvite Username';
+$lang['helpItemDescLogout'] = 'Ieşire din chat:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Mesaj privat:';
+$lang['helpItemCodePrivateMessage'] = '/msg Username Text';
+$lang['helpItemDescQueryOpen'] = 'Deschide un canal privat:';
+$lang['helpItemCodeQueryOpen'] = '/query Username';
+$lang['helpItemDescQueryClose'] = 'Închide un canal privat:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Descrie acţiune:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'Descrie acţiune în mesaj privat:';
+$lang['helpItemCodeDescribe'] = '/describe Username Text';
+$lang['helpItemDescIgnore'] = 'Ignoră/acceptă mesaj de la un utilizator:';
+$lang['helpItemCodeIgnore'] = '/ignore Username';
+$lang['helpItemDescIgnoreList'] = 'Arată lista cu utilizatorii ignoraţi:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Dă afară un utilizator (doar Moderatorii):';
+$lang['helpItemCodeKick'] = '/kick Username [Minutes banned]';
+$lang['helpItemDescUnban'] = 'Redă accesul la chat al unui utilizator (doar Moderatorii):';
+$lang['helpItemCodeUnban'] = '/unban Username';
+$lang['helpItemDescBans'] = 'Listează utilizatorii care au accesul interzis (doar Moderatorii):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Arată IP-ul utilizatorului (doar Moderatorii):';
+$lang['helpItemCodeWhois'] = '/whois Username';
+$lang['helpItemDescWho'] = 'Listează utilizatorii activi:';
+$lang['helpItemCodeWho'] = '/who [Channelname]';
+$lang['helpItemDescList'] = 'Listează canalele disponbile:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Aruncă zarul:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'Pentru a vizualiza acest chat trebuie să aveţi activat JavaScript-ul activat.';
+$lang['errorInvalidUser'] = 'Numele de utilizator incorect.';
+$lang['errorUserInUse'] = 'Numele de utilizator este deja folosit.';
+$lang['errorBanned'] = 'Accesul interzis utilizatorului sau persoanei cu acest IP.';
+$lang['errorMaxUsersLoggedIn'] = 'Chat-ul a atins numărul maxim de utilizatori.';
+$lang['errorChatClosed'] = 'Chat-ul este închis temporar.';
+$lang['logsTitle'] = 'Chat AJAX - Loguri';
+$lang['logsDate'] = 'Data';
+$lang['logsTime'] = 'Ora';
+$lang['logsSearch'] = 'Caută';
+$lang['logsPrivateChannels'] = 'Canale private';
+$lang['logsPrivateMessages'] = 'Mesaje private';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/ru.php b/library/ajaxchat/chat/lib/lang/ru.php
new file mode 100644
index 000000000..ac86531dc
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/ru.php
@@ -0,0 +1,125 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author SkyKnight
+ * @author Dmitry Plyonkin
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Имя';
+$lang['password'] = 'Пароль';
+$lang['login'] = 'Login';
+$lang['logout'] = 'Выйти';
+$lang['channel'] = 'Канал';
+$lang['style'] = 'Стиль';
+$lang['language'] = 'Язык';
+$lang['inputLineBreak'] = 'Нажмите SHIFT+ENTER, чтобы перейти на новую строку';
+$lang['messageSubmit'] = 'Отправить';
+$lang['registeredUsers'] = 'Только для зарегистрированных пользователей';
+$lang['onlineUsers'] = 'Пользователи онлайн';
+$lang['toggleAutoScroll'] = 'Вкл/выкл авто-прокрутку';
+$lang['toggleAudio'] = 'Вкл/выкл звук';
+$lang['toggleHelp'] = 'Показать/скрыть подсказку';
+$lang['toggleSettings'] = 'Показать/скрыть настройки';
+$lang['toggleOnlineList'] = 'Показать/скрыть список участников';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Цитата';
+$lang['bbCodeLabelCode'] = 'Код';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Цвет шрифта';
+$lang['bbCodeTitleBold'] = 'Жирный текст: [b]текст[/b]';
+$lang['bbCodeTitleItalic'] = 'Курсив: [i]текст[/i]';
+$lang['bbCodeTitleUnderline'] = 'Подчеркнутый текст: [u]текст[/u]';
+$lang['bbCodeTitleQuote'] = 'Цитата: [quote]текст[/quote] или [quote=автор]текст[/quote]';
+$lang['bbCodeTitleCode'] = 'Код: [code]текст[/code]';
+$lang['bbCodeTitleURL'] = 'Вставить ссылку: [url]http://example.org[/url] или [url=http://example.org]текст[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Цвет шрифта: [color=red]текст[/color]';
+$lang['help'] = 'Помощь';
+$lang['helpItemDescJoin'] = 'Присоедениться к каналу:';
+$lang['helpItemCodeJoin'] = '/join имя_канала';
+$lang['helpItemDescJoinCreate'] = 'Создать частный (приватный) канал:';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Пригласить кого-либо (например в частный канал):';
+$lang['helpItemCodeInvite'] = '/invite имя_пользователя';
+$lang['helpItemDescUninvite'] = 'Отозвать приглашение:';
+$lang['helpItemCodeUninvite'] = '/uninvite имя_пользователя';
+$lang['helpItemDescLogout'] = 'Выйти из чата:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Приватное сообщение:';
+$lang['helpItemCodePrivateMessage'] = '/msg Имя_пользователся Текст';
+$lang['helpItemDescQueryOpen'] = 'Открыть приватный канал:';
+$lang['helpItemCodeQueryOpen'] = '/query Имя_пользователя';
+$lang['helpItemDescQueryClose'] = 'Закрыть приватный канал:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Описать действия:';
+$lang['helpItemCodeAction'] = '/action Текст';
+$lang['helpItemDescDescribe'] = 'Описать действия в приватном сообщении:';
+$lang['helpItemCodeDescribe'] = '/describe Имя_пользователя Текст';
+$lang['helpItemDescIgnore'] = 'Игнорировать/принимать сообщения от пользователей:';
+$lang['helpItemCodeIgnore'] = '/ignore Имя_пользователся';
+$lang['helpItemDescIgnoreList'] = 'List ignored users:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Выгнать пользователся (Kick) (только модераторы и администраторы):';
+$lang['helpItemCodeKick'] = '/kick Имя_пользователя [Минуты]';
+$lang['helpItemDescUnban'] = 'Разбанить пользователя (Только модераторы и администраторы):';
+$lang['helpItemCodeUnban'] = '/unban Имя_пользователя';
+$lang['helpItemDescBans'] = 'Список забаненных пользователей (Только для модераторов):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Показать IP пользователся (Только модераторы и администраторы):';
+$lang['helpItemCodeWhois'] = '/whois Имя_пользователя';
+$lang['helpItemDescWho'] = 'Список доступных пользователей:';
+$lang['helpItemCodeWho'] = '/who [Имя_канала]';
+$lang['helpItemDescList'] = 'Список доступных каналов:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Бросить кубики:';
+$lang['helpItemCodeRoll'] = '/roll [количесво]d[количество сторон]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Настройки';
+$lang['settingsBBCode'] = 'Разрешить BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Разрешить ссылки:';
+$lang['settingsLineBreaks'] = 'Разрешить переводы строк:';
+$lang['settingsEmoticons'] = 'Разрешить смайлики:';
+$lang['settingsAutoFocus'] = 'Автоматически ставить курсор в поле ввода:';
+$lang['settingsMaxMessages'] = 'Маскимальное количество сообщений, отображающихся в чате:';
+$lang['settingsWordWrap'] = 'Переносить длинные слова:';
+$lang['settingsMaxWordLength'] = 'Максимально допустимая длина слова, которе не будет разбито для переноса:';
+$lang['settingsDateFormat'] = 'Формат даты и времени:';
+$lang['settingsPersistFontColor'] = 'Постоянный цвет шрифта:';
+$lang['settingsAudioVolume'] = 'Громкость:';
+$lang['settingsSoundReceive'] = 'Звук для входящих сообщений:';
+$lang['settingsSoundSend'] = 'Звук для исходящих сообщений:';
+$lang['settingsSoundEnter'] = 'Звук для оповещения о новом участнике в чате:';
+$lang['settingsSoundLeave'] = 'Звук для оповещения об уходе участника из чата:';
+$lang['settingsSoundChatBot'] = 'Звук для сообщений бота:';
+$lang['settingsSoundError'] = 'Звук для оповещений об ошибках:';
+$lang['settingsBlink'] = '"Моргать" заголовком окна при новом сообщении:';
+$lang['settingsBlinkInterval'] = 'Интервал "моргания" (в миллисекундах):';
+$lang['settingsBlinkIntervalNumber'] = 'Количество "морганий":';
+$lang['playSelectedSound'] = 'Воспроизвести выбранный звук';
+$lang['requiresJavaScript'] = 'Для корректной работы чата должен быть разрешен JavaScript.';
+$lang['errorInvalidUser'] = 'Неверное имя пользователя.';
+$lang['errorUserInUse'] = 'Имя занято.';
+$lang['errorBanned'] = 'Пользователь или IP забанены.';
+$lang['errorMaxUsersLoggedIn'] = 'В чате максимальное количество пользователей. Попробуйте зайти позднее.';
+$lang['errorChatClosed'] = 'Чат закрыт в настоящий момент.';
+$lang['logsTitle'] = 'AJAX Chat - История';
+$lang['logsDate'] = 'Дата';
+$lang['logsTime'] = 'Время';
+$lang['logsSearch'] = 'Поиск';
+$lang['logsPrivateChannels'] = 'Приватные каналы';
+$lang['logsPrivateMessages'] = 'Приватные сообщения';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/sk.php b/library/ajaxchat/chat/lib/lang/sk.php
new file mode 100644
index 000000000..fae99a785
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/sk.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Peter
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Meno';
+$lang['password'] = 'Heslo';
+$lang['login'] = 'Prihlásiť';
+$lang['logout'] = 'Odhlásiť';
+$lang['channel'] = 'Kanál';
+$lang['style'] = 'Štýl';
+$lang['language'] = 'Jazyk';
+$lang['inputLineBreak'] = 'Press SHIFT+ENTER to input a line break';
+$lang['messageSubmit'] = 'Poslať';
+$lang['registeredUsers'] = 'Registrovaní užívatelia';
+$lang['onlineUsers'] = 'Prihlásení užívatelia';
+$lang['toggleAutoScroll'] = 'Autoscroll on/off';
+$lang['toggleAudio'] = 'Sound on/off';
+$lang['toggleHelp'] = 'Show/hide help';
+$lang['toggleSettings'] = 'Show/hide settings';
+$lang['toggleOnlineList'] = 'Show/hide online list';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citovať';
+$lang['bbCodeLabelCode'] = 'Kód';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Farba písma';
+$lang['bbCodeTitleBold'] = 'Tučné: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Kurzívou: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podčiarknuté: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citovať text: [quote]text[/quote] alebo [quote=autor]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Zobraziť kód: [code]kód[/code]';
+$lang['bbCodeTitleURL'] = 'Vložiť URL: [url]http://www.example.org/[/url] alebo [url=http://www.example.org/]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Farba písma: [color=red]text[/color]';
+$lang['help'] = 'Nápoveda';
+$lang['helpItemDescJoin'] = 'Prihlásenie do kanálu:';
+$lang['helpItemCodeJoin'] = '/join Názov_kanálu';
+$lang['helpItemDescJoinCreate'] = 'Vytvoriť súkromný chat (Iba pre registrovaných užívateľov):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Pozvať niekoho k súkromnému rozhovoru:';
+$lang['helpItemCodeInvite'] = '/invite Meno_užívateľa';
+$lang['helpItemDescUninvite'] = 'Odriecť pozvanie:';
+$lang['helpItemCodeUninvite'] = '/uninvite Meno_užívateľa';
+$lang['helpItemDescLogout'] = 'Odhlásenie z chatu:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Súkromná správa:';
+$lang['helpItemCodePrivateMessage'] = '/msg Meno_užívateľa Text';
+$lang['helpItemDescQueryOpen'] = 'Otvoriť súkromný kanál:';
+$lang['helpItemCodeQueryOpen'] = '/query Meno_užívateľa';
+$lang['helpItemDescQueryClose'] = 'Zavrieť súkromný kanál:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Opísať akciu:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'Opísať akciu v súkromnej správe:';
+$lang['helpItemCodeDescribe'] = '/describe Meno_užívateľa Text';
+$lang['helpItemDescIgnore'] = 'Ignoruj/akceptuj správu od užívateľa:';
+$lang['helpItemCodeIgnore'] = '/ignore (accept) Meno_užívateľa';
+$lang['helpItemDescIgnoreList'] = 'Zoznam zamietnutých užívateľov:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Display user channel:';
+$lang['helpItemCodeWhereis'] = '/whereis Username';
+$lang['helpItemDescKick'] = 'Vylúčiť užívateľa (Iba Moderátori):';
+$lang['helpItemCodeKick'] = '/kick Meno_užívateľa [čas vylúčenia v minútach]';
+$lang['helpItemDescUnban'] = 'Prijať vylúčeného užívateľa (Iba Moderátori):';
+$lang['helpItemCodeUnban'] = '/unban Meno_užívateľa';
+$lang['helpItemDescBans'] = 'Zoznam vylúčených užívateľov (Iba Moderátori):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Zobraz IP užívateľa(Iba Moderátori):';
+$lang['helpItemCodeWhois'] = '/whois Meno_užívateľa';
+$lang['helpItemDescWho'] = 'Zoznam prihlásených užívateľov:';
+$lang['helpItemCodeWho'] = '/who [Meno_kanálu]';
+$lang['helpItemDescList'] = 'Zoznam dostupných kanálov:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Hodiť kocky:';
+$lang['helpItemCodeRoll'] = '/roll [číslo]d[strana]';
+$lang['helpItemDescNick'] = 'Change username:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = 'Settings';
+$lang['settingsBBCode'] = 'Enable BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Enable hyperlinks:';
+$lang['settingsLineBreaks'] = 'Enable line breaks:';
+$lang['settingsEmoticons'] = 'Enable emoticons:';
+$lang['settingsAutoFocus'] = 'Automatically set the focus on the input field:';
+$lang['settingsMaxMessages'] = 'Maximum number of messages in the chatlist:';
+$lang['settingsWordWrap'] = 'Enable wrapping of long words:';
+$lang['settingsMaxWordLength'] = 'Maximum length of a word before it gets wrapped:';
+$lang['settingsDateFormat'] = 'Format of date and time display:';
+$lang['settingsPersistFontColor'] = 'Persist font color:';
+$lang['settingsAudioVolume'] = 'Sound Volume:';
+$lang['settingsSoundReceive'] = 'Sound for incoming messages:';
+$lang['settingsSoundSend'] = 'Sound for outgoing messages:';
+$lang['settingsSoundEnter'] = 'Sound for login and channel enter messages:';
+$lang['settingsSoundLeave'] = 'Sound for logout and channel leave messages:';
+$lang['settingsSoundChatBot'] = 'Sound for chatbot messages:';
+$lang['settingsSoundError'] = 'Sound for error messages:';
+$lang['settingsBlink'] = 'Blink window title on new messages:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'Play selected sound';
+$lang['requiresJavaScript'] = 'Pre tento chat sa vyžaduje nainštalovať JavaScript.';
+$lang['errorInvalidUser'] = 'Neplatné užívateľské meno.';
+$lang['errorUserInUse'] = 'Použité užívateľské meno.';
+$lang['errorBanned'] = 'Užívateľ alebo IP je zakázané.';
+$lang['errorMaxUsersLoggedIn'] = 'Chat dosiahol maximálny počet prihlásených užívateľov.';
+$lang['errorChatClosed'] = 'Chat je momentálne nedostupný.';
+$lang['logsTitle'] = 'AJAX Chat - Záznamy';
+$lang['logsDate'] = 'Dátum';
+$lang['logsTime'] = 'Čas';
+$lang['logsSearch'] = 'Vyhľadávanie';
+$lang['logsPrivateChannels'] = 'Súkromný kanál';
+$lang['logsPrivateMessages'] = 'Súkromná správa';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/sl.php b/library/ajaxchat/chat/lib/lang/sl.php
new file mode 100644
index 000000000..6e4941532
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/sl.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Valter Pepelko
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'Klepetalnica';
+$lang['userName'] = 'Uporabniško ime';
+$lang['password'] = 'Geslo';
+$lang['login'] = 'Prijava';
+$lang['logout'] = 'Odjava';
+$lang['channel'] = 'Soba';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Jezik';
+$lang['inputLineBreak'] = 'Pritisnite SHIFT+ENTER za novo vrstico';
+$lang['messageSubmit'] = 'Pošlji';
+$lang['registeredUsers'] = 'Registrirani uporabniki';
+$lang['onlineUsers'] = 'Prisotni';
+$lang['toggleAutoScroll'] = 'Samodejno pomikanje besedila vklop/izklop';
+$lang['toggleAudio'] = 'Zvok vklop/izklop';
+$lang['toggleHelp'] = 'Pomoč prikaži/skrij';
+$lang['toggleSettings'] = 'Nastavitve prikaži/skrij';
+$lang['toggleOnlineList'] = 'Prisotni prikaži/skrij';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citiranje';
+$lang['bbCodeLabelCode'] = 'Koda';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Slika';
+$lang['bbCodeLabelColor'] = 'Barva črk';
+$lang['bbCodeTitleBold'] = 'Odebeljeno besedilo: [b]besedilo[/b]';
+$lang['bbCodeTitleItalic'] = 'Poševno besedilo: [i]besedilo[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podčrtano besedilo: [u]besedilo[/u]';
+$lang['bbCodeTitleQuote'] = 'Citirano besedilo: [quote]besedilo[/quote] ali [quote=autor]besedilo[/quote]';
+$lang['bbCodeTitleCode'] = 'Prikazovanje kode: [code]koda[/code]';
+$lang['bbCodeTitleURL'] = 'Vnesi URL: [url]http://www.primer.org/[/url] ali [url=http://www.primer.org/]besedilo[/url]';
+$lang['bbCodeTitleImg'] = 'Vstavi sliko: [img]http://priemr.org/slika.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Barva črk: [color=red]besedilo[/color]';
+$lang['help'] = 'Pomoč';
+$lang['helpItemDescJoin'] = 'Vstopi v sobo:';
+$lang['helpItemCodeJoin'] = '/join Ime sobe';
+$lang['helpItemDescJoinCreate'] = 'Izdelaj privatno sobo (samo registrirani uporabniki):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Povabi uporabnika v privatno sobo:';
+$lang['helpItemCodeInvite'] = '/invite Uporabnik';
+$lang['helpItemDescUninvite'] = 'Preklic povabila v privatno sobo uporabniku:';
+$lang['helpItemCodeUninvite'] = '/uninvite Uporabnik';
+$lang['helpItemDescLogout'] = 'Odjava:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privatno sporočilo:';
+$lang['helpItemCodePrivateMessage'] = '/msg Uporabnik Besedilo sporočila';
+$lang['helpItemDescQueryOpen'] = 'Odpri privatno sobo:';
+$lang['helpItemCodeQueryOpen'] = '/query Uporabnik';
+$lang['helpItemDescQueryClose'] = 'Zapri privatno sobo:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Opiši akcijo:';
+$lang['helpItemCodeAction'] = '/action Besedilo';
+$lang['helpItemDescDescribe'] = 'Opiši akcijo v privatnem sporočilu:';
+$lang['helpItemCodeDescribe'] = '/describe Uporabnik Besedilo';
+$lang['helpItemDescIgnore'] = 'Ignoriraj sporočila uporabnika:';
+$lang['helpItemCodeIgnore'] = '/ignore Uporabnik';
+$lang['helpItemDescIgnoreList'] = 'Seznam ignoriranih uporabnikov:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Prikaži v kateri sobi je uporabnik:';
+$lang['helpItemCodeWhereis'] = '/whereis Uporabnik';
+$lang['helpItemDescKick'] = 'Prepovej uporabnika (samo Moderatorji):';
+$lang['helpItemCodeKick'] = '/kick Uporabnik [čas prepovedi v minutah]';
+$lang['helpItemDescUnban'] = 'Prekliči prepoved uporabniku (samo Moderatorji):';
+$lang['helpItemCodeUnban'] = '/unban Uporabnik';
+$lang['helpItemDescBans'] = 'Seznam prepovedanih uporabnikov (samo Moderatorji):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Prikaži IP uporabnika (samo Moderatorji):';
+$lang['helpItemCodeWhois'] = '/whois Uporabnik';
+$lang['helpItemDescWho'] = 'Seznam prijavljenih uporabnikov:';
+$lang['helpItemCodeWho'] = '/who [Ime sobe]';
+$lang['helpItemDescList'] = 'Seznam dostopnih sob:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Vrzi kocko:';
+$lang['helpItemCodeRoll'] = '/roll [število]d[strani]';
+$lang['helpItemDescNick'] = 'Zamenjaj Uporabniško ime:';
+$lang['helpItemCodeNick'] = '/nick Uporabnik';
+$lang['settings'] = 'Nastavitve';
+$lang['settingsBBCode'] = 'Omogoči BB kodo:';
+$lang['settingsBBCodeImages'] = 'Omogoči slikovno BBCode:';
+$lang['settingsBBCodeColors'] = 'Omogoči barvo črk BBCode:';
+$lang['settingsHyperLinks'] = 'Omogoči hiperlinke:';
+$lang['settingsLineBreaks'] = 'Omogoči nove vrstice:';
+$lang['settingsEmoticons'] = 'Omogoči smeške:';
+$lang['settingsAutoFocus'] = 'Samodejno naravnaj fokus na polje za vnos besedila:';
+$lang['settingsMaxMessages'] = 'Maksimalno število sporočil na chat seznamu:';
+$lang['settingsWordWrap'] = 'Omogoči ovijanje dolgih besed:';
+$lang['settingsMaxWordLength'] = 'Maksimalna dolžina besed pred ovijanjem:';
+$lang['settingsDateFormat'] = 'Format prikaza datuma i ure:';
+$lang['settingsPersistFontColor'] = 'Stalna barva črk:';
+$lang['settingsAudioVolume'] = 'Višina zvoka:';
+$lang['settingsSoundReceive'] = 'Zvok za prispela sporočila:';
+$lang['settingsSoundSend'] = 'Zvok za poslana sporočila:';
+$lang['settingsSoundEnter'] = 'Zvok za prijavo in vstop v sobo:';
+$lang['settingsSoundLeave'] = 'Zvok za odjavo in izhod iz sobe:';
+$lang['settingsSoundChatBot'] = 'Zvok za chatbot sporočila:';
+$lang['settingsSoundError'] = 'Zvuk za sporočila o napakah:';
+$lang['settingsBlink'] = 'Trepetanje imena okna za nova sporočila:';
+$lang['settingsBlinkInterval'] = 'Interval trepetanja v milisekundah:';
+$lang['settingsBlinkIntervalNumber'] = 'Število intervalov trepetanja:';
+$lang['playSelectedSound'] = 'Reprodukcija izbranega zvoka';
+$lang['requiresJavaScript'] = 'Za uporabo klepetalnice moraš imeti nameščen JavaScript!';
+$lang['errorInvalidUser'] = 'Napačno uporabniško ime!';
+$lang['errorUserInUse'] = 'Uporabnik je že prijavljen!';
+$lang['errorBanned'] = 'Uporabnik ali ta IP je prepovedan!';
+$lang['errorMaxUsersLoggedIn'] = 'Na kleptu je prijavljeno maksimalno število uporabnikov!';
+$lang['errorChatClosed'] = 'Klepet je trenutno nedostopen!';
+$lang['logsTitle'] = 'Klepet - Beležke';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Ura';
+$lang['logsSearch'] = 'Iskanje';
+$lang['logsPrivateChannels'] = 'Privatne sobe';
+$lang['logsPrivateMessages'] = 'Privatna sporočila';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/sr.php b/library/ajaxchat/chat/lib/lang/sr.php
new file mode 100644
index 000000000..a14ba5512
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/sr.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Saša Stojanović
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Korisničko ime';
+$lang['password'] = 'Lozinka';
+$lang['login'] = 'Prijava';
+$lang['logout'] = 'Odjava';
+$lang['channel'] = 'Soba';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Jezik';
+$lang['inputLineBreak'] = 'Pritisnite SHIFT+ENTER za novi red';
+$lang['messageSubmit'] = 'Pošalji';
+$lang['registeredUsers'] = 'Registrovani korisnici';
+$lang['onlineUsers'] = 'Prisutni korisnici';
+$lang['toggleAutoScroll'] = 'Automatsko pomeranje teksta uključeno/isključeno';
+$lang['toggleAudio'] = 'Zvuk uključen/isključen';
+$lang['toggleHelp'] = 'Pomoć prikaži/sakrij';
+$lang['toggleSettings'] = 'Podešavanja prikaži/sakrij';
+$lang['toggleOnlineList'] = 'Prisutne korisnike prikaži/sakrij';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citiranje';
+$lang['bbCodeLabelCode'] = 'Kod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Boja fonta';
+$lang['bbCodeTitleBold'] = 'Podebljan tekst: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Iskrivljen tekst: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Podvučen tekst: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citiran tekst: [quote]text[/quote] ili [quote=autor]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Prikazivanje koda: [code]kod[/code]';
+$lang['bbCodeTitleURL'] = 'Unesi URL: [url]http://www.example.org/[/url] ili [url=http://www.example.org/]text[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Boja fonta: [color=red]text[/color]';
+$lang['help'] = 'Pomoć';
+$lang['helpItemDescJoin'] = 'Priključi se sobi:';
+$lang['helpItemCodeJoin'] = '/join Naziv sobe';
+$lang['helpItemDescJoinCreate'] = 'Napravi privatnu sobu (samo registrovani korisnici):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Pozovi korisnika u privatnu sobu:';
+$lang['helpItemCodeInvite'] = '/invite Korisnik';
+$lang['helpItemDescUninvite'] = 'Opoziv poziva u privatnu sobu korisnika:';
+$lang['helpItemCodeUninvite'] = '/uninvite Korisnik';
+$lang['helpItemDescLogout'] = 'Odjavljivanje:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privatna poruka:';
+$lang['helpItemCodePrivateMessage'] = '/msg Korisnik Tekst poruke';
+$lang['helpItemDescQueryOpen'] = 'Otvori privatnu sobu:';
+$lang['helpItemCodeQueryOpen'] = '/query Korisnik';
+$lang['helpItemDescQueryClose'] = 'Zatvori privatnu sobu:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Opiši akciju:';
+$lang['helpItemCodeAction'] = '/action Tekst';
+$lang['helpItemDescDescribe'] = 'Opiši akciju u privatnoj poruci:';
+$lang['helpItemCodeDescribe'] = '/describe Korisnik Tekst';
+$lang['helpItemDescIgnore'] = 'Prikazuj/neprikazuj poruke od korisnika:';
+$lang['helpItemCodeIgnore'] = '/ignore Korisnik';
+$lang['helpItemDescIgnoreList'] = 'Lista ignorisanih korisnika:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Prikaži u kojoj sobi je korisnik:';
+$lang['helpItemCodeWhereis'] = '/whereis Korisnik';
+$lang['helpItemDescKick'] = 'Zabrani korisnika (samo za Moderatore):';
+$lang['helpItemCodeKick'] = '/kick Korisnik [vreme zabrane u minutima]';
+$lang['helpItemDescUnban'] = 'Opozovi zabranu korisnika (samo za Moderatore):';
+$lang['helpItemCodeUnban'] = '/unban Korisnik';
+$lang['helpItemDescBans'] = 'Lista zabranjenih korisnika (samo za Moderatore):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Prikaži IP korisnika (samo za Moderatore):';
+$lang['helpItemCodeWhois'] = '/whois Korisnik';
+$lang['helpItemDescWho'] = 'Lista prijavljenih korisnika:';
+$lang['helpItemCodeWho'] = '/who [Ime sobe]';
+$lang['helpItemDescList'] = 'Lista dostupnih soba:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Baci kocku:';
+$lang['helpItemCodeRoll'] = '/roll [broj]d[strana]';
+$lang['helpItemDescNick'] = 'Promeni Korisničko ime:';
+$lang['helpItemCodeNick'] = '/nick Korisnik';
+$lang['settings'] = 'Podešavanja';
+$lang['settingsBBCode'] = 'Omogući BB kod:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Omogući hiperlinkove:';
+$lang['settingsLineBreaks'] = 'Omugući novi red:';
+$lang['settingsEmoticons'] = 'Omugući emocije:';
+$lang['settingsAutoFocus'] = 'Automatski podesi fokus na polje za unos teksta:';
+$lang['settingsMaxMessages'] = 'Maksimalni broj poruka u chat listi:';
+$lang['settingsWordWrap'] = 'Omogući omotavanje dugačkih reči:';
+$lang['settingsMaxWordLength'] = 'Maksimalna dužina reči pre nego što se omota:';
+$lang['settingsDateFormat'] = 'Format prikaza datuma i vremena:';
+$lang['settingsPersistFontColor'] = 'Stalna boja fonta:';
+$lang['settingsAudioVolume'] = 'Jačina zvuka:';
+$lang['settingsSoundReceive'] = 'Zvuk za primljene poruke:';
+$lang['settingsSoundSend'] = 'Zvuk za poslate poruke:';
+$lang['settingsSoundEnter'] = 'Zvuk za prijavljivanje i ulazak u sobu:';
+$lang['settingsSoundLeave'] = 'Zvuk za odjavljivanje i izlazak iz sobe:';
+$lang['settingsSoundChatBot'] = 'Zvuk za chatbot poruke:';
+$lang['settingsSoundError'] = 'Zvuk za poruke o grešci:';
+$lang['settingsBlink'] = 'Treptanje naziva prozora za nove poruke:';
+$lang['settingsBlinkInterval'] = 'Interval treptanja u milisekundama:';
+$lang['settingsBlinkIntervalNumber'] = 'Broj intervala treptanja:';
+$lang['playSelectedSound'] = 'Reprodukcija selektovanog zvuka';
+$lang['requiresJavaScript'] = 'JavaScript je neophodan za ovaj chat.';
+$lang['errorInvalidUser'] = 'Pogrešno korisničko ime.';
+$lang['errorUserInUse'] = 'Korisnik je već prijavljen.';
+$lang['errorBanned'] = 'Korisnik ili IP je zabranjen.';
+$lang['errorMaxUsersLoggedIn'] = 'Na chatu je prijavljen maksimalni broj korisnika.';
+$lang['errorChatClosed'] = 'Chat je trenutno nedostupan.';
+$lang['logsTitle'] = 'AJAX Chat - Beleške';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Vreme';
+$lang['logsSearch'] = 'Pretraga';
+$lang['logsPrivateChannels'] = 'Privatne sobe';
+$lang['logsPrivateMessages'] = 'Privatne poruke';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/sv.php b/library/ajaxchat/chat/lib/lang/sv.php
new file mode 100644
index 000000000..87f03a0ce
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/sv.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Eric [June 7,2008]
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Användarnamn';
+$lang['password'] = 'Lösenord';
+$lang['login'] = 'Logga In';
+$lang['logout'] = 'Logga Ut';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Språk';
+$lang['inputLineBreak'] = 'Håll ner SHIFT+ENTER för att göra ett radbryt';
+$lang['messageSubmit'] = 'Skicka';
+$lang['registeredUsers'] = 'Registerade Användare';
+$lang['onlineUsers'] = 'Användare OnLine';
+$lang['toggleAutoScroll'] = 'Autoscroll av/på';
+$lang['toggleAudio'] = 'Ljud av/på';
+$lang['toggleHelp'] = 'Visa/göm hjälp';
+$lang['toggleSettings'] = 'Visa/göm inställningar';
+$lang['toggleOnlineList'] = 'Visa/göm OnLine-listan';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Citera';
+$lang['bbCodeLabelCode'] = 'Kod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Textfärg';
+$lang['bbCodeTitleBold'] = 'Fet text: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Kursiv text: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Understruken text: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Citera text: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Visa kod: [code]code[/code]';
+$lang['bbCodeTitleURL'] = 'Lägg till URL: [url]http://www.example.org/[/url] or [url=http://www.example.org/]text[/url]';
+$lang['bbCodeTitleImg'] = 'Infoga bild: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Textfärg: [color=red]text[/color]';
+$lang['help'] = 'Hjälp';
+$lang['helpItemDescJoin'] = 'Anslut till kanal:';
+$lang['helpItemCodeJoin'] = '/join Kanalens namn';
+$lang['helpItemDescJoinCreate'] = 'Skapa privat rum (Endast registrerade användare):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Bjud in någon (eg till ett privat rum):';
+$lang['helpItemCodeInvite'] = '/invite Användare';
+$lang['helpItemDescUninvite'] = 'Upphäv inbjudan:';
+$lang['helpItemCodeUninvite'] = '/uninvite Användare';
+$lang['helpItemDescLogout'] = 'Logga ut från Chatten:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Privat meddelande:';
+$lang['helpItemCodePrivateMessage'] = '/msg Användare Text';
+$lang['helpItemDescQueryOpen'] = 'Öppna privat kanal:';
+$lang['helpItemCodeQueryOpen'] = '/query Användare';
+$lang['helpItemDescQueryClose'] = 'Stäng privat kanal:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Beskriv händelse:';
+$lang['helpItemCodeAction'] = '/action Text';
+$lang['helpItemDescDescribe'] = 'Beskriv händelse i privat meddelande:';
+$lang['helpItemCodeDescribe'] = '/describe Användare Text';
+$lang['helpItemDescIgnore'] = 'Ignorera/acceptera meddelande från användare:';
+$lang['helpItemCodeIgnore'] = '/ignore Användare';
+$lang['helpItemDescIgnoreList'] = 'Lista ignorerade användare:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Visa användare &amp; kanal:';
+$lang['helpItemCodeWhereis'] = '/whereis Användarnamn';
+$lang['helpItemDescKick'] = 'Sparka användare (Endast moderatorer):';
+$lang['helpItemCodeKick'] = '/kick Användare [Minuter bannad]';
+$lang['helpItemDescUnban'] = 'Upphäv banning av användare (Endast moderatorer):';
+$lang['helpItemCodeUnban'] = '/unban Användare';
+$lang['helpItemDescBans'] = 'Lista bannade användare (Endast moderatorer):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Visa användares IP (Endast moderatorer):';
+$lang['helpItemCodeWhois'] = '/whois Användare';
+$lang['helpItemDescWho'] = 'Lista användare online:';
+$lang['helpItemCodeWho'] = '/who [Kanalnamn]';
+$lang['helpItemDescList'] = 'Lista tillgängliga kanaler:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Rulla tärning:';
+$lang['helpItemCodeRoll'] = '/roll [siffra]d[sidor]';
+$lang['helpItemDescNick'] = 'Ändra användarnamn:';
+$lang['helpItemCodeNick'] = '/nick Användarnamn';
+$lang['settings'] = 'Inställningar';
+$lang['settingsBBCode'] = 'Aktivera BBCode:';
+$lang['settingsBBCodeImages'] = 'Aktivera BBCode bilder:';
+$lang['settingsBBCodeColors'] = 'Enable BBCode textfärg:';
+$lang['settingsHyperLinks'] = 'Aktivera länkar:';
+$lang['settingsLineBreaks'] = 'Aktivera radbryt:';
+$lang['settingsEmoticons'] = 'Aktivera smiley\'s:';
+$lang['settingsAutoFocus'] = 'Sätt fokus automatiskt på skrivraden:';
+$lang['settingsMaxMessages'] = 'Maximalt antal meddelanden i Chatlistan:';
+$lang['settingsWordWrap'] = 'Aktivera "wrapping" av långa ord:';
+$lang['settingsMaxWordLength'] = 'Maxlängd på ord innan det blir avdelat:';
+$lang['settingsDateFormat'] = 'Visningsformat av datum och tid:';
+$lang['settingsPersistFontColor'] = 'Behåll textfärg:';
+$lang['settingsAudioVolume'] = 'Volym:';
+$lang['settingsSoundReceive'] = 'Ljud för inkommande meddelanden:';
+$lang['settingsSoundSend'] = 'Ljud för utgående meddelanden:';
+$lang['settingsSoundEnter'] = 'Ljud för Logga in/Kanal meddelanden:';
+$lang['settingsSoundLeave'] = 'Ljud för Logga ut/lämna Kanal meddelanden:';
+$lang['settingsSoundChatBot'] = 'Ljud för Chatbot meddelanden:';
+$lang['settingsSoundError'] = 'Ljud för felmeddelanden:';
+$lang['settingsBlink'] = 'Blinka fönstrets titel vid nya meddelanden:';
+$lang['settingsBlinkInterval'] = 'Blinkintervall i millisekunder:';
+$lang['settingsBlinkIntervalNumber'] = 'Antal blinkintervaller:';
+$lang['playSelectedSound'] = 'Spela valt ljud';
+$lang['requiresJavaScript'] = 'JavaScript krävs för denna Chat.';
+$lang['errorInvalidUser'] = 'Ogiltigt användarnamn.';
+$lang['errorUserInUse'] = 'Användarnamnet är redan i bruk.';
+$lang['errorBanned'] = 'Användaren eller IP-numret är bannat.';
+$lang['errorMaxUsersLoggedIn'] = 'Chatten är full. Max antal användare är inloggade.';
+$lang['errorChatClosed'] = 'Chatten är stängd för tillfället.';
+$lang['logsTitle'] = 'AJAX Chat - Loggfiler';
+$lang['logsDate'] = 'Datum';
+$lang['logsTime'] = 'Tid';
+$lang['logsSearch'] = 'Sök';
+$lang['logsPrivateChannels'] = 'Privata Kanaler';
+$lang['logsPrivateMessages'] = 'Privata Meddelanden';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/th.php b/library/ajaxchat/chat/lib/lang/th.php
new file mode 100644
index 000000000..7ed3b1ef0
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/th.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ * @Translate by Charge01 @ http://www.thaira2lovers.co.cc
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'ชื่อผู้ใช้';
+$lang['password'] = 'รหัสผ่าน';
+$lang['login'] = 'เข้าสู่ระบบ';
+$lang['logout'] = 'ออกจากระบบ';
+$lang['channel'] = 'ห้องแชท';
+$lang['style'] = 'รูปแบบ';
+$lang['language'] = 'ภาษา';
+$lang['inputLineBreak'] = 'กด SHIFT+ENTER เพื่อเว้นบรรทัด';
+$lang['messageSubmit'] = 'ส่ง';
+$lang['registeredUsers'] = 'ผู้ใช้ที่ลงทะเบียนแล้ว';
+$lang['onlineUsers'] = 'ผู้ใช้ออนไลน์อยู่';
+$lang['toggleAutoScroll'] = 'เลื่อนอัตโนมัติ เปิด/ปิด';
+$lang['toggleAudio'] = 'เสียง เปิด/ปิด';
+$lang['toggleHelp'] = 'ช่วยเหลือ แสดง/ซ่อน';
+$lang['toggleSettings'] = 'ตั้งค่า แสดง/ซ่อน';
+$lang['toggleOnlineList'] = 'ผู้ใช้ออนไลน์ แสดง/ซ่อน';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'อ้างอิง';
+$lang['bbCodeLabelCode'] = 'โค๊ด';
+$lang['bbCodeLabelURL'] = 'ลิงค์';
+$lang['bbCodeLabelImg'] = 'ภาพ';
+$lang['bbCodeLabelColor'] = 'สีอักษร';
+$lang['bbCodeTitleBold'] = 'อักษรตัวหน้า: [b]ข้อความ[/b]';
+$lang['bbCodeTitleItalic'] = 'อักษรตัวเอียง: [i]ข้อความ[/i]';
+$lang['bbCodeTitleUnderline'] = 'อักษรขีดเส้นใต้: [u]ข้อความ[/u]';
+$lang['bbCodeTitleQuote'] = 'อ้างอิงข้อความ: [quote]ข้อความ[/quote] หรือ [quote=เจ้าของข้อความ]ข้อความ[/quote]';
+$lang['bbCodeTitleCode'] = 'แสดงโค๊ด: [code]โค๊ด[/code]';
+$lang['bbCodeTitleURL'] = 'แทรกลิงค์: [url]http://example.org[/url] or [url=http://example.org]ข้อความ[/url]';
+$lang['bbCodeTitleImg'] = 'แทรกภาพ: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'ตัวอักษรสี: [color=red]ข้อความ[/color]';
+$lang['help'] = 'ช่วยเหลือ';
+$lang['helpItemDescJoin'] = 'ร่วมห้องแชท:';
+$lang['helpItemCodeJoin'] = '/join ชื่อห้องแชท';
+$lang['helpItemDescJoinCreate'] = 'สร้างห้องส่วนตัว (สำหรับสมาชิกเท่านั้น):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'เชิญใครสักคน (เช่น คุยในห้องส่วนตัว):';
+$lang['helpItemCodeInvite'] = '/invite ชื่อผู้ใช้';
+$lang['helpItemDescUninvite'] = 'ถอนคำเชิญ:';
+$lang['helpItemCodeUninvite'] = '/uninvite ชื่อผู้ใช้';
+$lang['helpItemDescLogout'] = 'ออกจากระบบห้องแชท:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'ข้อความส่วนตัว:';
+$lang['helpItemCodePrivateMessage'] = '/msg ชื่อผู้ใช้ ข้อความ';
+$lang['helpItemDescQueryOpen'] = 'เปิดห้องส่วนตัว:';
+$lang['helpItemCodeQueryOpen'] = '/query ชื่อผู้ใช้';
+$lang['helpItemDescQueryClose'] = 'ปิดห้องส่วนตัว:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'บอกสิ่งกระทำ:';
+$lang['helpItemCodeAction'] = '/action สิ่งที่ำกำลังทำ';
+$lang['helpItemDescDescribe'] = 'บอกสิ่งที่กระทำในข้อความส่วนตัว:';
+$lang['helpItemCodeDescribe'] = '/describe ชื่อผู้ใช้ ข้อความ';
+$lang['helpItemDescIgnore'] = 'ไม่สนใจ/ยอมรับ ข้อความจากผู้ใช้:';
+$lang['helpItemCodeIgnore'] = '/ignore ชื่อผู้ใช้';
+$lang['helpItemDescIgnoreList'] = 'รายการผู้ใช้ที่ไม่สนใจ:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'แสดงผู้ใช้อยู่ในห้อง:';
+$lang['helpItemCodeWhereis'] = '/whereis ชื่อผู้ใช้';
+$lang['helpItemDescKick'] = 'ไล่ผู้ใช้ (ผู้ดูแลเท่านั้น):';
+$lang['helpItemCodeKick'] = '/kick ผู้ใช้ [แบนในหนึ่งนาที]';
+$lang['helpItemDescUnban'] = 'ยกเลิกแบนผู้ใช้ (ผู้ดูแลเท่านั้น):';
+$lang['helpItemCodeUnban'] = '/unban ชื่อผู้ใช้';
+$lang['helpItemDescBans'] = 'รายการผู้ใช้ถูกแบน (ผู้ดูแลเท่านั้น):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'แสดง IP ของผู้ใช้ (ผู้ดูแลเท่านั้น):';
+$lang['helpItemCodeWhois'] = '/whois ชื่อผู้ใช้';
+$lang['helpItemDescWho'] = 'รายชื่อผู้ใช้ที่ออนไลน์:';
+$lang['helpItemCodeWho'] = '/who [ชื่อห้อง]';
+$lang['helpItemDescList'] = 'รายชื่อห้องที่มีอยู่:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'ทอยลูกเต๋า:';
+$lang['helpItemCodeRoll'] = '/roll [เลข]d[ด้าน]';
+$lang['helpItemDescNick'] = 'เปลี่ยนชื่อผู้ใช้:';
+$lang['helpItemCodeNick'] = '/nick ชื่อผู้ใช้ใหม่';
+$lang['settings'] = 'ตั้งค่า';
+$lang['settingsBBCode'] = 'เปิดใช้งาน BBCode:';
+$lang['settingsBBCodeImages'] = 'เปิดใช้งาน BBCode ภาพ:';
+$lang['settingsBBCodeColors'] = 'เปิดใช้งาน อักษรสี BBCode:';
+$lang['settingsHyperLinks'] = 'เปิดใช้งานลิงค์:';
+$lang['settingsLineBreaks'] = 'เปิดใช้งานการเว้นบรรทัด:';
+$lang['settingsEmoticons'] = 'เปิดใช้งาน รูปแสดงอารมณ์:';
+$lang['settingsAutoFocus'] = 'ตั้งโฟกัสในช่องพิมพ์อัตโนมัติ:';
+$lang['settingsMaxMessages'] = 'อักษรที่สามารถให้พิมพ์ได้มากสุดในข้อความ:';
+$lang['settingsWordWrap'] = 'เปิดใช้งานการเว้นบรรทัดข้อความที่ยาว:';
+$lang['settingsMaxWordLength'] = 'ความาวของคำก่อนที่จะเว้นบรรทัดใหม่ให้:';
+$lang['settingsDateFormat'] = 'รูปแบบวันที่และเวลา:';
+$lang['settingsPersistFontColor'] = 'สีอักษรทั้งข้อความ:';
+$lang['settingsAudioVolume'] = 'ระดับเสียง:';
+$lang['settingsSoundReceive'] = 'เสียงสำหรับข้อความเข้า:';
+$lang['settingsSoundSend'] = 'เสียงสำหรับข้อความออกไป:';
+$lang['settingsSoundEnter'] = 'เสียงสำหรับเข้าระบบและเข้าห้อง:';
+$lang['settingsSoundLeave'] = 'เสียงสำหรับออกจากระบบและออกจากห้อง:';
+$lang['settingsSoundChatBot'] = 'เสียงสำหรับข้อความจาำกระบบ:';
+$lang['settingsSoundError'] = 'เสียงสำหรับข้อความผิดพลาด:';
+$lang['settingsBlink'] = 'มีสัญญาณ กระพริบบน Title Bar เมื่อมีข้อความใหม่:';
+$lang['settingsBlinkInterval'] = 'Blink interval in milliseconds:';
+$lang['settingsBlinkIntervalNumber'] = 'Number of blink intervals:';
+$lang['playSelectedSound'] = 'เล่นเสียงที่เลือก';
+$lang['requiresJavaScript'] = 'ต้องการจาวาสคริปสำหรับห้องแชท';
+$lang['errorInvalidUser'] = 'ชื่อผู้ใช้ผิดพลาด';
+$lang['errorUserInUse'] = 'ชื่อผู้ใช้นี้กำลังใช้งานอยู่';
+$lang['errorBanned'] = 'ผู้ใช้นี้หรือ IP นี้ถูกแบน';
+$lang['errorMaxUsersLoggedIn'] = 'ห้องแชทเต็ม';
+$lang['errorChatClosed'] = 'ห้องแชทถูกปิดชั่วคราว';
+$lang['logsTitle'] = 'AJAX Chat - บันทึกการใช้งาน';
+$lang['logsDate'] = 'วันที่';
+$lang['logsTime'] = 'เวลา';
+$lang['logsSearch'] = 'ค้นหา';
+$lang['logsPrivateChannels'] = 'ห้องส่วนตัว';
+$lang['logsPrivateMessages'] = 'ข้อความส่วนตัว';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/tr.php b/library/ajaxchat/chat/lib/lang/tr.php
new file mode 100644
index 000000000..00f7dfaa6
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/tr.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Cydonian
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Üye adı';
+$lang['password'] = 'Şifre';
+$lang['login'] = 'Giriş';
+$lang['logout'] = 'Çıkış';
+$lang['channel'] = 'Kanal';
+$lang['style'] = 'Stil';
+$lang['language'] = 'Dil';
+$lang['inputLineBreak'] = 'Bir satır ara için SHIFT+ENTER tuşlarına basınız';
+$lang['messageSubmit'] = 'Gönder';
+$lang['registeredUsers'] = 'Kayıtlı Üyeler';
+$lang['onlineUsers'] = 'Çevrimiçi üyeler';
+$lang['toggleAutoScroll'] = 'Otomatik kaydırma aç/kapat';
+$lang['toggleAudio'] = 'Ses aç/kapat';
+$lang['toggleHelp'] = 'Yardımı göster/sakla';
+$lang['toggleSettings'] = 'Ayarları göster/sakla';
+$lang['toggleOnlineList'] = 'Çevrimiçi listesini göster/sakla';
+$lang['bbCodeLabelBold'] = 'b';
+$lang['bbCodeLabelItalic'] = 'i';
+$lang['bbCodeLabelUnderline'] = 'u';
+$lang['bbCodeLabelQuote'] = 'Büyük';
+$lang['bbCodeLabelCode'] = 'Kod';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Resim';
+$lang['bbCodeLabelColor'] = 'Renkli Yazı';
+$lang['bbCodeTitleBold'] = 'Kalın text: [b]text[/b]';
+$lang['bbCodeTitleItalic'] = 'Eğik text: [i]text[/i]';
+$lang['bbCodeTitleUnderline'] = 'Altçizgili text: [u]text[/u]';
+$lang['bbCodeTitleQuote'] = 'Büyük text: [quote]text[/quote] or [quote=author]text[/quote]';
+$lang['bbCodeTitleCode'] = 'Kod gösterim: [code]kod[/code]';
+$lang['bbCodeTitleURL'] = 'URL gir: [url]http://example.org[/url] veya [url=http://example.org]text[/url]';
+$lang['bbCodeTitleImg'] = 'Resim gir: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Font Rengi: [color=red]text[/color]';
+$lang['help'] = 'Yardım';
+$lang['helpItemDescJoin'] = 'Bir kanala girin:';
+$lang['helpItemCodeJoin'] = '/join kanalismi';
+$lang['helpItemDescJoinCreate'] = 'Özel oda aç (Sadece kayıtlı üyeler için):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Birisini Davet Et (örn. özel bir odaya):';
+$lang['helpItemCodeInvite'] = '/invite üyeismi';
+$lang['helpItemDescUninvite'] = 'Daveti İptal Et:';
+$lang['helpItemCodeUninvite'] = '/uninvite üyeismi';
+$lang['helpItemDescLogout'] = 'Sohbetten Çık:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Özel mesaj:';
+$lang['helpItemCodePrivateMessage'] = '/msg üyeismi mesaj';
+$lang['helpItemDescQueryOpen'] = 'Özel bir kanal aç:';
+$lang['helpItemCodeQueryOpen'] = '/query üyeismi';
+$lang['helpItemDescQueryClose'] = 'Özel bir kanalı kapat:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Aksiyon:';
+$lang['helpItemCodeAction'] = '/action mesaj';
+$lang['helpItemDescDescribe'] = 'Özel mesajda aksiyon:';
+$lang['helpItemCodeDescribe'] = '/describe üyeismi mesaj';
+$lang['helpItemDescIgnore'] = 'Üyeden gelen mesajları Blokla/KabulEt:';
+$lang['helpItemCodeIgnore'] = '/ignore üyeismi';
+$lang['helpItemDescIgnoreList'] = 'Bloklanmış üyeleri listele:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Üyenin kanalını göster:';
+$lang['helpItemCodeWhereis'] = '/whereis üyeismi';
+$lang['helpItemDescKick'] = 'Üyeyi at (Sadece Moderatörler):';
+$lang['helpItemCodeKick'] = '/kick üyeismi [Yasaklanan Dakika]';
+$lang['helpItemDescUnban'] = 'Üyenin yasağını kaldır (Sadece Moderatörler):';
+$lang['helpItemCodeUnban'] = '/unban üyeismi';
+$lang['helpItemDescBans'] = 'Yasaklanan üyeleri listele (Sadece Moderatörler):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Üyenin IP adresini göster (Sadece Moderatörler):';
+$lang['helpItemCodeWhois'] = '/whois üyeismi';
+$lang['helpItemDescWho'] = 'Çevrimiçi üyeleri listele:';
+$lang['helpItemCodeWho'] = '/who [kanalismi]';
+$lang['helpItemDescList'] = 'Kullanılabilir kanalları listele:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Zarları at:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = 'Üye ismini değiştir:';
+$lang['helpItemCodeNick'] = '/nick üyeismi';
+$lang['settings'] = 'Ayarlar';
+$lang['settingsBBCode'] = 'BBCode u aç:';
+$lang['settingsBBCodeImages'] = 'Resim BBCode u aç:';
+$lang['settingsBBCodeColors'] = 'Font Rengi BBCode u aç:';
+$lang['settingsHyperLinks'] = 'Bağlantıları (link) aç:';
+$lang['settingsLineBreaks'] = 'Satır aralarını aç:';
+$lang['settingsEmoticons'] = 'Emoticons ı aç:';
+$lang['settingsAutoFocus'] = 'Giriş kutusuna otomatik odaklan:';
+$lang['settingsMaxMessages'] = 'Sohbet listesinde maksimum mesaj sayısı:';
+$lang['settingsWordWrap'] = 'Uzun kelimeleri kısaltmayı aç:';
+$lang['settingsMaxWordLength'] = 'Kısaltılacak kelimenin maksimum uzunluğu:';
+$lang['settingsDateFormat'] = 'Tarih ve zaman gösterim formatı:';
+$lang['settingsPersistFontColor'] = 'Kalıcı font rengi:';
+$lang['settingsAudioVolume'] = 'Ses Düzeyi:';
+$lang['settingsSoundReceive'] = 'Gelen mesaj sesi:';
+$lang['settingsSoundSend'] = 'Giden mesaj sesi:';
+$lang['settingsSoundEnter'] = 'Giriş ve kanala giriş sesi:';
+$lang['settingsSoundLeave'] = 'Çıkış ve kanaldan çıkış sesi:';
+$lang['settingsSoundChatBot'] = 'Chatbot mesajları sesi:';
+$lang['settingsSoundError'] = 'Hata mesajları sesi:';
+$lang['settingsBlink'] = 'Yeni mesaj geldiğinde pencere başlığını kırp:';
+$lang['settingsBlinkInterval'] = 'Milisaniye olarak kırpma aralığı:';
+$lang['settingsBlinkIntervalNumber'] = 'Kırpma sayısı aralığı:';
+$lang['playSelectedSound'] = 'Seçili sesi çal';
+$lang['requiresJavaScript'] = 'Bu Sohbet için JavaScript gereklidir.';
+$lang['errorInvalidUser'] = 'Geçersiz üyeismi.';
+$lang['errorUserInUse'] = 'Üyeismi kullanımda.';
+$lang['errorBanned'] = 'Üye veya IP yasaklanmıştır.';
+$lang['errorMaxUsersLoggedIn'] = 'Sohbet maksimum kullanıcı sayısına ulaştı.';
+$lang['errorChatClosed'] = 'Sohbet şu anda kapalıdır.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Tarih';
+$lang['logsTime'] = 'Saat';
+$lang['logsSearch'] = 'Ara';
+$lang['logsPrivateChannels'] = 'Özel Kanallar';
+$lang['logsPrivateMessages'] = 'Özel Mesajlar';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/uk.php b/library/ajaxchat/chat/lib/lang/uk.php
new file mode 100644
index 000000000..a7d80c16b
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/uk.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author Yuriy Smetana (yura@stryi.com.ua, http://joomla.org.ua)
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = 'Ім\'я користувача';
+$lang['password'] = 'Пароль';
+$lang['login'] = 'Увійти';
+$lang['logout'] = 'Вийти';
+$lang['channel'] = 'Кімната';
+$lang['style'] = 'Стиль';
+$lang['language'] = 'Мова';
+$lang['inputLineBreak'] = 'Використовуйте SHIFT+ENTER для нового рядка';
+$lang['messageSubmit'] = 'Надіслати';
+$lang['registeredUsers'] = 'Зареєстровані користувачі';
+$lang['onlineUsers'] = 'Зараз в Чаті';
+$lang['toggleAutoScroll'] = 'Прогортувати: так/ні';
+$lang['toggleAudio'] = 'Звік: так/ні';
+$lang['toggleHelp'] = 'Показати допомогу: так/ні';
+$lang['toggleSettings'] = 'Показати налаштування: так/ні';
+$lang['toggleOnlineList'] = 'Хто в Чаті: так/ні';
+$lang['bbCodeLabelBold'] = 'Ж';
+$lang['bbCodeLabelItalic'] = 'Н';
+$lang['bbCodeLabelUnderline'] = 'П';
+$lang['bbCodeLabelQuote'] = 'Цитата';
+$lang['bbCodeLabelCode'] = 'Код';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = 'Колір шрифту';
+$lang['bbCodeTitleBold'] = 'Жирний текст: [b]текст[/b]';
+$lang['bbCodeTitleItalic'] = 'Текст курсивом: [i]текст[/i]';
+$lang['bbCodeTitleUnderline'] = 'Підкреслений текст: [u]текст[/u]';
+$lang['bbCodeTitleQuote'] = 'Цитований текст: [quote]текст[/quote] чи [quote=author]текст[/quote]';
+$lang['bbCodeTitleCode'] = 'Показати код: [code]код[/code]';
+$lang['bbCodeTitleURL'] = 'Показати URL: [url]http://example.org[/url] or [url=http://example.org]текст[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = 'Колір шрифту: [color=red]текст[/color]';
+$lang['help'] = 'Допомога';
+$lang['helpItemDescJoin'] = 'Зайти в кімнату:';
+$lang['helpItemCodeJoin'] = '/join Назва_Кімнати';
+$lang['helpItemDescJoinCreate'] = 'Створити приватну кімнату (тільки для зареєстрованих користувачів):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = 'Запросити когось (наприклад до приватної кімнати):';
+$lang['helpItemCodeInvite'] = '/invite Користувач';
+$lang['helpItemDescUninvite'] = 'Відмінити запрошення:';
+$lang['helpItemCodeUninvite'] = '/uninvite Користувач';
+$lang['helpItemDescLogout'] = 'Вийти з чату:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = 'Приватне повідомлення:';
+$lang['helpItemCodePrivateMessage'] = '/msg Користувач Текст';
+$lang['helpItemDescQueryOpen'] = 'Створити приватну кімнату:';
+$lang['helpItemCodeQueryOpen'] = '/query Користувач';
+$lang['helpItemDescQueryClose'] = 'Закрити приватну кімнату:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = 'Описати чим займаєтесь:';
+$lang['helpItemCodeAction'] = '/action Що Робите';
+$lang['helpItemDescDescribe'] = 'Описати чим займаєтесь, в приватному повідомленні:';
+$lang['helpItemCodeDescribe'] = '/describe Кому Що Робите';
+$lang['helpItemDescIgnore'] = 'Ігнорувати/приймати повідомлення від користувача:';
+$lang['helpItemCodeIgnore'] = '/ignore Користувач';
+$lang['helpItemDescIgnoreList'] = 'Перелік ігнорованих користувачів:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = 'Показати кімнату користувача:';
+$lang['helpItemCodeWhereis'] = '/whereis Користувач';
+$lang['helpItemDescKick'] = 'Вигнати користувача (тільки для модераторів):';
+$lang['helpItemCodeKick'] = '/kick Користувач [на скільки хвилин]';
+$lang['helpItemDescUnban'] = 'Розблокувати користувача (тільки для модераторів):';
+$lang['helpItemCodeUnban'] = '/unban Користувач';
+$lang['helpItemDescBans'] = 'Перелік заблокованих користувачів:';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = 'Показати ІР користувача (тільки для модераторів):';
+$lang['helpItemCodeWhois'] = '/whois Користувач';
+$lang['helpItemDescWho'] = 'Хто в Чаті:';
+$lang['helpItemCodeWho'] = '/who [Кімната]';
+$lang['helpItemDescList'] = 'Перелік кімнат:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = 'Кинути кості:';
+$lang['helpItemCodeRoll'] = '/roll [к-сть]d[к-сть сторін]';
+$lang['helpItemDescNick'] = 'Змінити ім\'я користувача:';
+$lang['helpItemCodeNick'] = '/nick Користувач';
+$lang['settings'] = 'Налаштування';
+$lang['settingsBBCode'] = 'Дозволити коди BB:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = 'Дозволити посилання:';
+$lang['settingsLineBreaks'] = 'Дозволити багаторядковість:';
+$lang['settingsEmoticons'] = 'Дозволити хихоньки:';
+$lang['settingsAutoFocus'] = 'Автоматично встановлювати фокус на полі вводу:';
+$lang['settingsMaxMessages'] = 'Максимальна кількість повідомлень у вікні Чату:';
+$lang['settingsWordWrap'] = 'Розділювати довгі слова:';
+$lang['settingsMaxWordLength'] = 'Максимальна довжина слова після якої його буде розділено:';
+$lang['settingsDateFormat'] = 'Формат дати та часу:';
+$lang['settingsPersistFontColor'] = 'Колір для привернення уваги:';
+$lang['settingsAudioVolume'] = 'Гучність:';
+$lang['settingsSoundReceive'] = 'Звук для отриманих повідомлень:';
+$lang['settingsSoundSend'] = 'Звук для надісланих повідомлень:';
+$lang['settingsSoundEnter'] = 'Звук для події входу в Чат чи кімнату:';
+$lang['settingsSoundLeave'] = 'Звук для події виходу з Чату чи кімнати:';
+$lang['settingsSoundChatBot'] = 'Звук для системних повідомлень:';
+$lang['settingsSoundError'] = 'Звук для помилок:';
+$lang['settingsBlink'] = 'Сигналізувати при появі нових повідомлень (блимання заголовку вікна):';
+$lang['settingsBlinkInterval'] = 'Тривалість блимання заголовку вікна:';
+$lang['settingsBlinkIntervalNumber'] = 'Кількість блимань:';
+$lang['playSelectedSound'] = 'Відтворити обраний звук';
+$lang['requiresJavaScript'] = 'Для цього Чату потрібно дозволити JavaScript.';
+$lang['errorInvalidUser'] = 'Неправильне ім\'я користувача.';
+$lang['errorUserInUse'] = 'Таке ім\'я вже використовується';
+$lang['errorBanned'] = 'Користувач або IP заблокований.';
+$lang['errorMaxUsersLoggedIn'] = 'В Чаті максимальна кількість учасників.';
+$lang['errorChatClosed'] = 'Чат, тимчасово, закрито.';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = 'Дата';
+$lang['logsTime'] = 'Час';
+$lang['logsSearch'] = 'Пошук';
+$lang['logsPrivateChannels'] = 'Приватні кімнати';
+$lang['logsPrivateMessages'] = 'Приватні повідомлення';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/lang/zh-tw.php b/library/ajaxchat/chat/lib/lang/zh-tw.php
new file mode 100644
index 000000000..d39fe6b14
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/zh-tw.php
@@ -0,0 +1,123 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = '使用者帳號';
+$lang['password'] = '密碼';
+$lang['login'] = '登入';
+$lang['logout'] = '登出';
+$lang['channel'] = '房間';
+$lang['style'] = '版面風格';
+$lang['language'] = '語言';
+$lang['inputLineBreak'] = '按 SHIFT+ENTER 換行';
+$lang['messageSubmit'] = '發送';
+$lang['registeredUsers'] = '已註冊會員';
+$lang['onlineUsers'] = '在線會員';
+$lang['toggleAutoScroll'] = '自動捲動 開/關';
+$lang['toggleAudio'] = '音效 開/關';
+$lang['toggleHelp'] = '開啟/關閉 使用說明';
+$lang['toggleSettings'] = '開啟/關閉 選項設定';
+$lang['toggleOnlineList'] = '開啟/關閉 線上名單';
+$lang['bbCodeLabelBold'] = '粗體';
+$lang['bbCodeLabelItalic'] = '斜體';
+$lang['bbCodeLabelUnderline'] = '底線';
+$lang['bbCodeLabelQuote'] = '引用';
+$lang['bbCodeLabelCode'] = '代碼';
+$lang['bbCodeLabelURL'] = '連結';
+$lang['bbCodeLabelImg'] = '圖片';
+$lang['bbCodeLabelColor'] = '字體顏色';
+$lang['bbCodeTitleBold'] = '粗體字: [b]文字[/b]';
+$lang['bbCodeTitleItalic'] = '斜體字: [i]文字[/i]';
+$lang['bbCodeTitleUnderline'] = '底線: [u]文字[/u]';
+$lang['bbCodeTitleQuote'] = '引用文字: [quote]文字[/quote] 或 [quote=某人]文字[/quote]';
+$lang['bbCodeTitleCode'] = '代碼: [code]代碼[/code]';
+$lang['bbCodeTitleURL'] = '插入URL: [url]http://example.org[/url] 或 [url=http://example.org]文字[/url]';
+$lang['bbCodeTitleImg'] = '插入圖片: [img]http://example.org/image.png[/img]';
+$lang['bbCodeTitleColor'] = '字體顏色: [color=red]文字[/color]';
+$lang['help'] = '使用說明';
+$lang['helpItemDescJoin'] = '進入一個房間:';
+$lang['helpItemCodeJoin'] = '/join 房間名';
+$lang['helpItemDescJoinCreate'] = '進入自己的私人房間(會員限定):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = '邀請某人(進入自己的私人房):';
+$lang['helpItemCodeInvite'] = '/invite 使用者帳號';
+$lang['helpItemDescUninvite'] = '收回邀請函:';
+$lang['helpItemCodeUninvite'] = '/uninvite 使用者帳號';
+$lang['helpItemDescLogout'] = '登出:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = '悄悄話:';
+$lang['helpItemCodePrivateMessage'] = '/msg 使用者帳號 文字';
+$lang['helpItemDescQueryOpen'] = '開啟一間私人房:';
+$lang['helpItemCodeQueryOpen'] = '/query 使用者帳號';
+$lang['helpItemDescQueryClose'] = '關閉私人房:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = '描述動作:';
+$lang['helpItemCodeAction'] = '/action 文字';
+$lang['helpItemDescDescribe'] = '用悄悄話描述動作:';
+$lang['helpItemCodeDescribe'] = '/describe 使用者帳號 文字';
+$lang['helpItemDescIgnore'] = '忽略/接受某人的訊息:';
+$lang['helpItemCodeIgnore'] = '/ignore 使用者帳號';
+$lang['helpItemDescIgnoreList'] = '列出所有被忽略訊息的人:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = '尋找某人的位置:';
+$lang['helpItemCodeWhereis'] = '/whereis 使用者帳號';
+$lang['helpItemDescKick'] = '踢除某人(版主限定):';
+$lang['helpItemCodeKick'] = '/kick 使用者帳號 [Minutes banned]';
+$lang['helpItemDescUnban'] = '解除封鎖某人(版主限定):';
+$lang['helpItemCodeUnban'] = '/unban 使用者帳號';
+$lang['helpItemDescBans'] = '列出所有被禁止使用的人(版主限定):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = '查詢某人的IP(版主限定):';
+$lang['helpItemCodeWhois'] = '/whois 使用者帳號';
+$lang['helpItemDescWho'] = '列出所有在房間的人:';
+$lang['helpItemCodeWho'] = '/who [房間名]';
+$lang['helpItemDescList'] = '列出所有可進去的房間:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = '擲骰子:';
+$lang['helpItemCodeRoll'] = '/roll [幾次]d[幾種點]';
+$lang['helpItemDescNick'] = '更換暱稱:';
+$lang['helpItemCodeNick'] = '/nick 使用者帳號';
+$lang['settings'] = '選項';
+$lang['settingsBBCode'] = '啟用BBCode:';
+$lang['settingsBBCodeImages'] = '啟用圖形的BBCode:';
+$lang['settingsBBCodeColors'] = '啟用字體顏色的BBCode:';
+$lang['settingsHyperLinks'] = '啟用超連結:';
+$lang['settingsLineBreaks'] = '啟用換行符號';
+$lang['settingsEmoticons'] = '啟用表情圖示:';
+$lang['settingsAutoFocus'] = '自動切換焦點至輸入框:';
+$lang['settingsMaxMessages'] = '對話框裡訊息的最大數量:';
+$lang['settingsWordWrap'] = '遇長字彙時隨螢幕大小自動斷行:';
+$lang['settingsMaxWordLength'] = '字被截斷之前的最大長度:';
+$lang['settingsDateFormat'] = '時間格式:';
+$lang['settingsPersistFontColor'] = '固定字體顏色:';
+$lang['settingsAudioVolume'] = '音效的音量:';
+$lang['settingsSoundReceive'] = '新訊息的音效:';
+$lang['settingsSoundSend'] = '舊訊息的音效:';
+$lang['settingsSoundEnter'] = '登入和進入房間的音效:';
+$lang['settingsSoundLeave'] = '登出和離開房間的音效:';
+$lang['settingsSoundChatBot'] = '系統訊息的音效:';
+$lang['settingsSoundError'] = '錯誤訊息的音效:';
+$lang['settingsBlink'] = '當有新訊息時閃動標題:';
+$lang['settingsBlinkInterval'] = '閃動的間隔時間(毫秒):';
+$lang['settingsBlinkIntervalNumber'] = '閃動次數:';
+$lang['playSelectedSound'] = '播放選取的音效';
+$lang['requiresJavaScript'] = '請啟用JavaScript才能登入!';
+$lang['errorInvalidUser'] = '使用者名稱無法使用……';
+$lang['errorUserInUse'] = '使用者名稱正在使用中……';
+$lang['errorBanned'] = '使用者名稱或IP已被封鎖……';
+$lang['errorMaxUsersLoggedIn'] = '聊天室已客滿,無法進入……';
+$lang['errorChatClosed'] = '聊天室目前已關閉……';
+$lang['logsTitle'] = 'AJAX Chat - Logs';
+$lang['logsDate'] = '日期';
+$lang['logsTime'] = '時間';
+$lang['logsSearch'] = '搜尋';
+$lang['logsPrivateChannels'] = '私人房';
+$lang['logsPrivateMessages'] = '悄悄話';
+?>
diff --git a/library/ajaxchat/chat/lib/lang/zh.php b/library/ajaxchat/chat/lib/lang/zh.php
new file mode 100644
index 000000000..1d18f0bc0
--- /dev/null
+++ b/library/ajaxchat/chat/lib/lang/zh.php
@@ -0,0 +1,124 @@
+<?php
+/*
+ * @package AJAX_Chat
+ * @author Sebastian Tschan
+ * @author mikespook
+ * @copyright (c) Sebastian Tschan
+ * @license Modified MIT License
+ * @link https://blueimp.net/ajax/
+ */
+
+$lang = array();
+$lang['title'] = 'AJAX Chat';
+$lang['userName'] = '用户名';
+$lang['password'] = '密码';
+$lang['login'] = '登录';
+$lang['logout'] = '退出';
+$lang['channel'] = '频道';
+$lang['style'] = '样式';
+$lang['language'] = '语言';
+$lang['inputLineBreak'] = '按 SHIFT + ENTER 输入新行';
+$lang['messageSubmit'] = '提交';
+$lang['registeredUsers'] = '注册用户';
+$lang['onlineUsers'] = '在线用户';
+$lang['toggleAutoScroll'] = '自动滚动 开/关';
+$lang['toggleAudio'] = '声音 开/关';
+$lang['toggleHelp'] = '显示/隐藏 帮助';
+$lang['toggleSettings'] = '显示/隐藏 设置';
+$lang['toggleOnlineList'] = '显示/隐藏 在线列表';
+$lang['bbCodeLabelBold'] = '粗体';
+$lang['bbCodeLabelItalic'] = '斜体';
+$lang['bbCodeLabelUnderline'] = '下划线';
+$lang['bbCodeLabelQuote'] = '引用';
+$lang['bbCodeLabelCode'] = '代码';
+$lang['bbCodeLabelURL'] = 'URL';
+$lang['bbCodeLabelImg'] = 'Image';
+$lang['bbCodeLabelColor'] = '文字颜色';
+$lang['bbCodeTitleBold'] = '粗体:[b]文字[/b]';
+$lang['bbCodeTitleItalic'] = '斜体:[i]文字[/i]';
+$lang['bbCodeTitleUnderline'] = '下划线:[u]文字[/u]';
+$lang['bbCodeTitleQuote'] = '引用:[quote]引用[/quote] or [quote=作者]引用[/quote]';
+$lang['bbCodeTitleCode'] = '显示代码:[code]代码[/code]';
+$lang['bbCodeTitleURL'] = '插入 URL:[url]http://example.org[/url] 或者 [url=http://example.org]文字[/url]';
+$lang['bbCodeTitleImg'] = 'Insert image: [img]http://example.org/image.jpg[/img]';
+$lang['bbCodeTitleColor'] = '文字颜色:[color=red]文字[/color]';
+$lang['help'] = '帮助';
+$lang['helpItemDescJoin'] = '加入频道';
+$lang['helpItemCodeJoin'] = '/join 频道名';
+$lang['helpItemDescJoinCreate'] = '创建私人房间(仅限注册用户):';
+$lang['helpItemCodeJoinCreate'] = '/join';
+$lang['helpItemDescInvite'] = '邀请某人(例如进入私人房间):';
+$lang['helpItemCodeInvite'] = '/invite 用户名';
+$lang['helpItemDescUninvite'] = '取消邀请:';
+$lang['helpItemCodeUninvite'] = '/uninvite 用户名';
+$lang['helpItemDescLogout'] = '推出登录:';
+$lang['helpItemCodeLogout'] = '/quit';
+$lang['helpItemDescPrivateMessage'] = '悄悄话';
+$lang['helpItemCodePrivateMessage'] = '/msg 用户名 内容';
+$lang['helpItemDescQueryOpen'] = '打开私人频道:';
+$lang['helpItemCodeQueryOpen'] = '/query 用户名';
+$lang['helpItemDescQueryClose'] = '关闭私人频道:';
+$lang['helpItemCodeQueryClose'] = '/query';
+$lang['helpItemDescAction'] = '动作描述:';
+$lang['helpItemCodeAction'] = '/action 文字';
+$lang['helpItemDescDescribe'] = '在悄悄话中做动作:';
+$lang['helpItemCodeDescribe'] = '/describe 用户名 文字';
+$lang['helpItemDescIgnore'] = '忽略/接受用户消息:';
+$lang['helpItemCodeIgnore'] = '/ignore 用户名';
+$lang['helpItemDescIgnoreList'] = '列出忽略用户:';
+$lang['helpItemCodeIgnoreList'] = '/ignore';
+$lang['helpItemDescWhereis'] = '显示用户频道:';
+$lang['helpItemCodeWhereis'] = '/whereis 用户名';
+$lang['helpItemDescKick'] = '踢出用户(仅限版主):';
+$lang['helpItemCodeKick'] = '/kick 用户名 [倒数秒数]';
+$lang['helpItemDescUnban'] = '取消用户禁言(仅限版主):';
+$lang['helpItemCodeUnban'] = '/unban 用户名';
+$lang['helpItemDescBans'] = '列出禁言用户(仅限版主):';
+$lang['helpItemCodeBans'] = '/bans';
+$lang['helpItemDescWhois'] = '显示用户 IP(仅限版主):';
+$lang['helpItemCodeWhois'] = '/whois 用户名';
+$lang['helpItemDescWho'] = '列出在线用户:';
+$lang['helpItemCodeWho'] = '/who [频道名]';
+$lang['helpItemDescList'] = '列出可用频道:';
+$lang['helpItemCodeList'] = '/list';
+$lang['helpItemDescRoll'] = '摇骰子:';
+$lang['helpItemCodeRoll'] = '/roll [number]d[sides]';
+$lang['helpItemDescNick'] = '修改用户名:';
+$lang['helpItemCodeNick'] = '/nick Username';
+$lang['settings'] = '设置';
+$lang['settingsBBCode'] = '可用 BBCode:';
+$lang['settingsBBCodeImages'] = 'Enable image BBCode:';
+$lang['settingsBBCodeColors'] = 'Enable font color BBCode:';
+$lang['settingsHyperLinks'] = '可用超链接:';
+$lang['settingsLineBreaks'] = '可用换行:';
+$lang['settingsEmoticons'] = '可用表情符号:';
+$lang['settingsAutoFocus'] = '自动将焦点定位于输入框:';
+$lang['settingsMaxMessages'] = '消息列表中的最大消息数:';
+$lang['settingsWordWrap'] = '开启超宽换行:';
+$lang['settingsMaxWordLength'] = '行宽:';
+$lang['settingsDateFormat'] = '时间和日期显示格式:';
+$lang['settingsPersistFontColor'] = '字体颜色:';
+$lang['settingsAudioVolume'] = '音量:';
+$lang['settingsSoundReceive'] = '声音提示进入信息:';
+$lang['settingsSoundSend'] = '声音提示离开信息:';
+$lang['settingsSoundEnter'] = '声音提示登录或进入频道信息:';
+$lang['settingsSoundLeave'] = '声音提示退出或离开频道信息:';
+$lang['settingsSoundChatBot'] = '声音提示机器人信息:';
+$lang['settingsSoundError'] = '声音提示错误信息:';
+$lang['settingsBlink'] = '有新消息时闪烁窗口标题:';
+$lang['settingsBlinkInterval'] = '空闲间隔毫秒数:';
+$lang['settingsBlinkIntervalNumber'] = '空闲间隔数:';
+$lang['playSelectedSound'] = '播放选择的声音';
+$lang['requiresJavaScript'] = '需要 JavaScript。';
+$lang['errorInvalidUser'] = '不合法的用户名。';
+$lang['errorUserInUse'] = '用户名已被使用。';
+$lang['errorBanned'] = '用户名或 IP 被禁止。';
+$lang['errorMaxUsersLoggedIn'] = '聊天室达到最大用户数。';
+$lang['errorChatClosed'] = '当前聊天室暂停服务。';
+$lang['logsTitle'] = 'AJAX Chat - 日志';
+$lang['logsDate'] = '日期';
+$lang['logsTime'] = '时间';
+$lang['logsSearch'] = '搜索';
+$lang['logsPrivateChannels'] = '私人频道';
+$lang['logsPrivateMessages'] = '私人消息';
+?> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/template/loggedIn.html b/library/ajaxchat/chat/lib/template/loggedIn.html
new file mode 100644
index 000000000..16a75ebe9
--- /dev/null
+++ b/library/ajaxchat/chat/lib/template/loggedIn.html
@@ -0,0 +1,387 @@
+<?xml version="1.0" encoding="[CONTENT_ENCODING/]"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[LANG_CODE/]" lang="[LANG_CODE/]" dir="[BASE_DIRECTION/]">
+
+<head>
+ <meta http-equiv="Content-Type" content="[CONTENT_TYPE/]" />
+ <title>[LANG]title[/LANG]</title>
+ <style type="text/css">
+ body {
+ padding:0;
+ margin:0;
+ }
+ </style>
+ [STYLE_SHEETS/]
+ <!--[if lt IE 7]>
+ <link rel="stylesheet" type="text/css" href="css/ie5-6.css"/>
+ <script type="text/javascript">
+ var isIElt7 = true;
+ </script>
+ <![endif]-->
+ <script src="js/chat.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/custom.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/lang/[LANG_CODE/].js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/config.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/FABridge.js" type="text/javascript" charset="UTF-8"></script>
+ <script type="text/javascript">
+ // <![CDATA[
+ function toggleContainer(containerID, hideContainerIDs) {
+ if(hideContainerIDs) {
+ for(var i=0; i<hideContainerIDs.length; i++) {
+ ajaxChat.showHide(hideContainerIDs[i], 'none');
+ }
+ }
+ ajaxChat.showHide(containerID);
+ if(typeof arguments.callee.styleProperty == 'undefined') {
+ if(typeof isIElt7 != 'undefined') {
+ arguments.callee.styleProperty = 'marginRight';
+ } else {
+ arguments.callee.styleProperty = 'right';
+ }
+ }
+ var containerWidth = document.getElementById(containerID).offsetWidth;
+ if(containerWidth) {
+ document.getElementById('chatList').style[arguments.callee.styleProperty] = (containerWidth+28)+'px';
+ } else {
+ document.getElementById('chatList').style[arguments.callee.styleProperty] = '20px';
+ }
+ }
+
+ function initialize() {
+ ajaxChat.updateButton('audio', 'audioButton');
+ ajaxChat.updateButton('autoScroll', 'autoScrollButton');
+ document.getElementById('bbCodeSetting').checked = ajaxChat.getSetting('bbCode');
+ document.getElementById('bbCodeImagesSetting').checked = ajaxChat.getSetting('bbCodeImages');
+ document.getElementById('bbCodeColorsSetting').checked = ajaxChat.getSetting('bbCodeColors');
+ document.getElementById('hyperLinksSetting').checked = ajaxChat.getSetting('hyperLinks');
+ document.getElementById('lineBreaksSetting').checked = ajaxChat.getSetting('lineBreaks');
+ document.getElementById('emoticonsSetting').checked = ajaxChat.getSetting('emoticons');
+ document.getElementById('autoFocusSetting').checked = ajaxChat.getSetting('autoFocus');
+ document.getElementById('maxMessagesSetting').value = ajaxChat.getSetting('maxMessages');
+ document.getElementById('wordWrapSetting').checked = ajaxChat.getSetting('wordWrap');
+ document.getElementById('maxWordLengthSetting').value = ajaxChat.getSetting('maxWordLength');
+ document.getElementById('dateFormatSetting').value = ajaxChat.getSetting('dateFormat');
+ document.getElementById('persistFontColorSetting').checked = ajaxChat.getSetting('persistFontColor');
+ for(var i=0; i<document.getElementById('audioVolumeSetting').options.length; i++) {
+ if(document.getElementById('audioVolumeSetting').options[i].value == ajaxChat.getSetting('audioVolume')) {
+ document.getElementById('audioVolumeSetting').options[i].selected = true;
+ break;
+ }
+ }
+ ajaxChat.fillSoundSelection('soundReceiveSetting', ajaxChat.getSetting('soundReceive'));
+ ajaxChat.fillSoundSelection('soundSendSetting', ajaxChat.getSetting('soundSend'));
+ ajaxChat.fillSoundSelection('soundEnterSetting', ajaxChat.getSetting('soundEnter'));
+ ajaxChat.fillSoundSelection('soundLeaveSetting', ajaxChat.getSetting('soundLeave'));
+ ajaxChat.fillSoundSelection('soundChatBotSetting', ajaxChat.getSetting('soundChatBot'));
+ ajaxChat.fillSoundSelection('soundErrorSetting', ajaxChat.getSetting('soundError'));
+ document.getElementById('blinkSetting').checked = ajaxChat.getSetting('blink');
+ document.getElementById('blinkIntervalSetting').value = ajaxChat.getSetting('blinkInterval');
+ document.getElementById('blinkIntervalNumberSetting').value = ajaxChat.getSetting('blinkIntervalNumber');
+ }
+
+ ajaxChatConfig.loginChannelID = parseInt('[LOGIN_CHANNEL_ID/]');
+ ajaxChatConfig.sessionName = '[SESSION_NAME/]';
+ ajaxChatConfig.cookieExpiration = parseInt('[COOKIE_EXPIRATION/]');
+ ajaxChatConfig.cookiePath = '[COOKIE_PATH/]';
+ ajaxChatConfig.cookieDomain = '[COOKIE_DOMAIN/]';
+ ajaxChatConfig.cookieSecure = '[COOKIE_SECURE/]';
+ ajaxChatConfig.chatBotName = decodeURIComponent('[CHAT_BOT_NAME/]');
+ ajaxChatConfig.chatBotID = '[CHAT_BOT_ID/]';
+ ajaxChatConfig.allowUserMessageDelete = parseInt('[ALLOW_USER_MESSAGE_DELETE/]');
+ ajaxChatConfig.inactiveTimeout = parseInt('[INACTIVE_TIMEOUT/]');
+ ajaxChatConfig.privateChannelDiff = parseInt('[PRIVATE_CHANNEL_DIFF/]');
+ ajaxChatConfig.privateMessageDiff = parseInt('[PRIVATE_MESSAGE_DIFF/]');
+ ajaxChatConfig.showChannelMessages = parseInt('[SHOW_CHANNEL_MESSAGES/]');
+ ajaxChatConfig.messageTextMaxLength = parseInt('[MESSAGE_TEXT_MAX_LENGTH/]');
+ ajaxChatConfig.socketServerEnabled = parseInt('[SOCKET_SERVER_ENABLED/]');
+ ajaxChatConfig.socketServerHost = decodeURIComponent('[SOCKET_SERVER_HOST/]');
+ ajaxChatConfig.socketServerPort = parseInt('[SOCKET_SERVER_PORT/]');
+ ajaxChatConfig.socketServerChatID = parseInt('[SOCKET_SERVER_CHAT_ID/]');
+
+ ajaxChat.init(ajaxChatConfig, ajaxChatLang, true, true, true, initialize);
+ // ]]>
+ </script>
+</head>
+
+<body>
+ <div id="content">
+ <div id="headlineContainer">
+ <h1>[LANG]title[/LANG]</h1>
+ </div>
+ <div id="logoutChannelContainer">
+ <input type="button" id="logoutButton" value="[LANG]logout[/LANG]" onclick="ajaxChat.logout();"/>
+ <label for="channelSelection">[LANG]channel[/LANG]:</label>
+ <select id="channelSelection" onchange="ajaxChat.switchChannel(this.options[this.selectedIndex].value);">[CHANNEL_OPTIONS/]</select>
+ <label for="styleSelection">[LANG]style[/LANG]:</label>
+ <select id="styleSelection" onchange="ajaxChat.setActiveStyleSheet(ajaxChat.getSelectedStyle());">[STYLE_OPTIONS/]</select>
+ <label for="languageSelection">[LANG]language[/LANG]:</label>
+ <select id="languageSelection" onchange="ajaxChat.switchLanguage(this.value);">[LANGUAGE_OPTIONS/]</select>
+ </div>
+ <div id="statusIconContainer" class="statusContainerOn"></div>
+ <!--[if lt IE 7]>
+ <div></div>
+ <![endif]-->
+ <div id="chatList"></div>
+ <div id="inputFieldContainer">
+ <textarea id="inputField" rows="1" cols="50" title="[LANG]inputLineBreak[/LANG]" onkeypress="ajaxChat.handleInputFieldKeyPress(event);" onkeyup="ajaxChat.handleInputFieldKeyUp(event);"></textarea>
+ </div>
+ <div id="submitButtonContainer">
+ <span id="messageLengthCounter">0/[MESSAGE_TEXT_MAX_LENGTH/]</span>
+ <input type="button" id="submitButton" value="[LANG]messageSubmit[/LANG]" onclick="ajaxChat.sendMessage();"/>
+ </div>
+ <div id="emoticonsContainer" dir="ltr"></div>
+ <div id="bbCodeContainer">
+ <input type="button" value="[LANG]bbCodeLabelBold[/LANG]" title="[LANG]bbCodeTitleBold[/LANG]" onclick="ajaxChat.insertBBCode('b');" style="font-weight:bold;"/>
+ <input type="button" value="[LANG]bbCodeLabelItalic[/LANG]" title="[LANG]bbCodeTitleItalic[/LANG]" onclick="ajaxChat.insertBBCode('i');" style="font-style:italic;"/>
+ <input type="button" value="[LANG]bbCodeLabelUnderline[/LANG]" title="[LANG]bbCodeTitleUnderline[/LANG]" onclick="ajaxChat.insertBBCode('u');" style="text-decoration:underline;"/>
+ <input type="button" value="[LANG]bbCodeLabelQuote[/LANG]" title="[LANG]bbCodeTitleQuote[/LANG]" onclick="ajaxChat.insertBBCode('quote');"/>
+ <input type="button" value="[LANG]bbCodeLabelCode[/LANG]" title="[LANG]bbCodeTitleCode[/LANG]" onclick="ajaxChat.insertBBCode('code');"/>
+ <input type="button" value="[LANG]bbCodeLabelURL[/LANG]" title="[LANG]bbCodeTitleURL[/LANG]" onclick="ajaxChat.insertBBCode('url');"/>
+ <input type="button" value="[LANG]bbCodeLabelImg[/LANG]" title="[LANG]bbCodeTitleImg[/LANG]" onclick="ajaxChat.insertBBCode('img');"/>
+ <input type="button" value="[LANG]bbCodeLabelColor[/LANG]" title="[LANG]bbCodeTitleColor[/LANG]" onclick="ajaxChat.showHide('colorCodesContainer', null);"/>
+ </div>
+ <div id="colorCodesContainer" style="display:none;" dir="ltr"></div>
+ <div id="optionsContainer">
+ <input type="image" src="img/pixel.gif" class="button" id="helpButton" alt="[LANG]toggleHelp[/LANG]" title="[LANG]toggleHelp[/LANG]" onclick="toggleContainer('helpContainer', new Array('onlineListContainer','settingsContainer'));"/>
+ <input type="image" src="img/pixel.gif" class="button" id="settingsButton" alt="[LANG]toggleSettings[/LANG]" title="[LANG]toggleSettings[/LANG]" onclick="toggleContainer('settingsContainer', new Array('onlineListContainer','helpContainer'));"/>
+ <input type="image" src="img/pixel.gif" class="button" id="onlineListButton" alt="[LANG]toggleOnlineList[/LANG]" title="[LANG]toggleOnlineList[/LANG]" onclick="toggleContainer('onlineListContainer', new Array('settingsContainer','helpContainer'));"/>
+ <input type="image" src="img/pixel.gif" class="button" id="audioButton" alt="[LANG]toggleAudio[/LANG]" title="[LANG]toggleAudio[/LANG]" onclick="ajaxChat.toggleSetting('audio', 'audioButton');"/>
+ <input type="image" src="img/pixel.gif" class="button" id="autoScrollButton" alt="[LANG]toggleAutoScroll[/LANG]" title="[LANG]toggleAutoScroll[/LANG]" onclick="ajaxChat.toggleSetting('autoScroll', 'autoScrollButton');"/>
+ </div>
+ <div id="onlineListContainer">
+ <h3>[LANG]onlineUsers[/LANG]</h3>
+ <div id="onlineList"></div>
+ </div>
+ <div id="helpContainer" style="display:none;">
+ <h3>[LANG]help[/LANG]</h3>
+ <div id="helpList">
+ <table>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescJoin[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeJoin[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescJoinCreate[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeJoinCreate[/LANG]</td>
+
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescInvite[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeInvite[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescUninvite[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeUninvite[/LANG]</td>
+ </tr>
+
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescLogout[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeLogout[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescPrivateMessage[/LANG]</td>
+ <td class="code">[LANG]helpItemCodePrivateMessage[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+
+ <td class="desc">[LANG]helpItemDescQueryOpen[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeQueryOpen[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescQueryClose[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeQueryClose[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescAction[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeAction[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescDescribe[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeDescribe[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescIgnore[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeIgnore[/LANG]</td>
+
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescIgnoreList[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeIgnoreList[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescWhereis[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeWhereis[/LANG]</td>
+ </tr>
+
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescKick[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeKick[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescUnban[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeUnban[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+
+ <td class="desc">[LANG]helpItemDescBans[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeBans[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescWhois[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeWhois[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescWho[/LANG]</td>
+
+ <td class="code">[LANG]helpItemCodeWho[/LANG]</td>
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescList[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeList[/LANG]</td>
+ </tr>
+ <tr class="rowEven">
+ <td class="desc">[LANG]helpItemDescRoll[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeRoll[/LANG]</td>
+
+ </tr>
+ <tr class="rowOdd">
+ <td class="desc">[LANG]helpItemDescNick[/LANG]</td>
+ <td class="code">[LANG]helpItemCodeNick[/LANG]</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div id="settingsContainer" style="display:none;">
+ <h3>[LANG]settings[/LANG]</h3>
+ <div id="settingsList">
+ <table>
+ <tr class="rowOdd">
+ <td><label for="bbCodeSetting">[LANG]settingsBBCode[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="bbCodeSetting" onclick="ajaxChat.setSetting('bbCode', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="bbCodeImagesSetting">[LANG]settingsBBCodeImages[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="bbCodeImagesSetting" onclick="ajaxChat.setSetting('bbCodeImages', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="bbCodeColorsSetting">[LANG]settingsBBCodeColors[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="bbCodeColorsSetting" onclick="ajaxChat.setSetting('bbCodeColors', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="hyperLinksSetting">[LANG]settingsHyperLinks[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="hyperLinksSetting" onclick="ajaxChat.setSetting('hyperLinks', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="lineBreaksSetting">[LANG]settingsLineBreaks[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="lineBreaksSetting" onclick="ajaxChat.setSetting('lineBreaks', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="emoticonsSetting">[LANG]settingsEmoticons[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="emoticonsSetting" onclick="ajaxChat.setSetting('emoticons', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="autoFocusSetting">[LANG]settingsAutoFocus[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="autoFocusSetting" onclick="ajaxChat.setSetting('autoFocus', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="maxMessagesSetting">[LANG]settingsMaxMessages[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="maxMessagesSetting" onchange="ajaxChat.setSetting('maxMessages', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="wordWrapSetting">[LANG]settingsWordWrap[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="wordWrapSetting" onclick="ajaxChat.setSetting('wordWrap', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="maxWordLengthSetting">[LANG]settingsMaxWordLength[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="maxWordLengthSetting" onchange="ajaxChat.setSetting('maxWordLength', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="dateFormatSetting">[LANG]settingsDateFormat[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="dateFormatSetting" onchange="ajaxChat.setSetting('dateFormat', this.value);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="persistFontColorSetting">[LANG]settingsPersistFontColor[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="persistFontColorSetting" onclick="ajaxChat.setPersistFontColor(this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="audioVolumeSetting">[LANG]settingsAudioVolume[/LANG]</label></td>
+ <td class="setting">
+ <select class="left" id="audioVolumeSetting" onchange="ajaxChat.setAudioVolume(this.options[this.selectedIndex].value);">
+ <option value="1.0">100 %</option>
+ <option value="0.9">90 %</option>
+ <option value="0.8">80 %</option>
+ <option value="0.7">70 %</option>
+ <option value="0.6">60 %</option>
+ <option value="0.5">50 %</option>
+ <option value="0.4">40 %</option>
+ <option value="0.3">30 %</option>
+ <option value="0.2">20 %</option>
+ <option value="0.1">10 %</option>
+ </select>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundReceiveSetting">[LANG]settingsSoundReceive[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundReceiveSetting" onchange="ajaxChat.setSetting('soundReceive', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundSendSetting">[LANG]settingsSoundSend[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundSendSetting" onchange="ajaxChat.setSetting('soundSend', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundEnterSetting">[LANG]settingsSoundEnter[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundEnterSetting" onchange="ajaxChat.setSetting('soundEnter', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundLeaveSetting">[LANG]settingsSoundLeave[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundLeaveSetting" onchange="ajaxChat.setSetting('soundLeave', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundChatBotSetting">[LANG]settingsSoundChatBot[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundChatBotSetting" onchange="ajaxChat.setSetting('soundChatBot', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundErrorSetting">[LANG]settingsSoundError[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundErrorSetting" onchange="ajaxChat.setSetting('soundError', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="blinkSetting">[LANG]settingsBlink[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="blinkSetting" onclick="ajaxChat.setSetting('blink', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="blinkIntervalSetting">[LANG]settingsBlinkInterval[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="blinkIntervalSetting" onchange="ajaxChat.setSetting('blinkInterval', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="blinkIntervalNumberSetting">[LANG]settingsBlinkIntervalNumber[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="blinkIntervalNumberSetting" onchange="ajaxChat.setSetting('blinkIntervalNumber', parseInt(this.value));"/></td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <!--
+ Please retain the full copyright notice below including the link to blueimp.net.
+ This not only gives respect to the amount of time given freely by the developer
+ but also helps build interest, traffic and use of AJAX Chat.
+
+ Thanks,
+ Sebastian Tschan
+ //-->
+ <div id="copyright"><a href="https://blueimp.net/ajax/">AJAX Chat</a> &copy; <a href="https://blueimp.net">blueimp.net</a></div>
+ </div>
+ <div id="flashInterfaceContainer"></div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/template/loggedOut.html b/library/ajaxchat/chat/lib/template/loggedOut.html
new file mode 100644
index 000000000..ba8a8a4a9
--- /dev/null
+++ b/library/ajaxchat/chat/lib/template/loggedOut.html
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="[CONTENT_ENCODING/]"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[LANG_CODE/]" lang="[LANG_CODE/]" dir="[BASE_DIRECTION/]">
+
+<head>
+ <meta http-equiv="Content-Type" content="[CONTENT_TYPE/]" />
+ <title>[LANG]title[/LANG]</title>
+ <style type="text/css">
+ body {
+ padding:0;
+ margin:0;
+ }
+ </style>
+ [STYLE_SHEETS/]
+ <!--[if lt IE 7]>
+ <link rel="stylesheet" type="text/css" href="css/ie5-6.css"/>
+ <![endif]-->
+ <script src="js/chat.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/lang/[LANG_CODE/].js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/config.js" type="text/javascript" charset="UTF-8"></script>
+ <script type="text/javascript">
+ // <![CDATA[
+ function initializeLoginPage() {
+ document.getElementById('userNameField').focus();
+ if(!ajaxChat.isCookieEnabled()) {
+ var node = document.createElement('div');
+ var text = document.createTextNode(ajaxChatLang['errorCookiesRequired']);
+ node.appendChild(text);
+ document.getElementById('errorContainer').appendChild(node);
+ }
+ }
+
+ ajaxChatConfig.sessionName = '[SESSION_NAME/]';
+ ajaxChatConfig.cookieExpiration = parseInt('[COOKIE_EXPIRATION/]');
+ ajaxChatConfig.cookiePath = '[COOKIE_PATH/]';
+ ajaxChatConfig.cookieDomain = '[COOKIE_DOMAIN/]';
+ ajaxChatConfig.cookieSecure = '[COOKIE_SECURE/]';
+
+ ajaxChat.init(ajaxChatConfig, ajaxChatLang, true, true, false);
+ // ]]>
+ </script>
+</head>
+
+<body onload="initializeLoginPage();">
+ <div id="loginContent">
+ <div id="loginHeadlineContainer">
+ <h1>[LANG]title[/LANG]</h1>
+ </div>
+ <form id="loginForm" action="[LOGIN_URL/]" method="post" enctype="application/x-www-form-urlencoded">
+ <div id="loginFormContainer">
+ <input type="hidden" name="login" id="loginField" value="login"/>
+ <input type="hidden" name="redirect" id="redirectField" value="[REDIRECT_URL/]"/>
+ <div><label for="userNameField">[LANG]userName[/LANG]:</label><br />
+ <input type="text" name="userName" id="userNameField" maxlength="[USER_NAME_MAX_LENGTH/]"/></div>
+ <div><label for="passwordField">[LANG]password[/LANG]*:</label><br />
+ <input type="password" name="password" id="passwordField"/></div>
+ <div><label for="channelField">[LANG]channel[/LANG]:</label><br />
+ <select name="channelName" id="channelField">[CHANNEL_OPTIONS/]</select></div>
+ <div><label for="languageSelection">[LANG]language[/LANG]:</label><br />
+ <select id="languageSelection" name="lang" onchange="ajaxChat.switchLanguage(this.value);">[LANGUAGE_OPTIONS/]</select></div>
+ <div><input type="submit" name="submit" id="loginButton" value="[LANG]login[/LANG]"/></div>
+ <div id="loginRegisteredUsers">* [LANG]registeredUsers[/LANG]</div>
+ </div>
+ </form>
+ <div id="errorContainer">[ERROR_MESSAGES/]<noscript><div>[LANG]requiresJavaScript[/LANG]</div></noscript></div>
+ <!--
+ Please retain the full copyright notice below including the link to blueimp.net.
+ This not only gives respect to the amount of time given freely by the developer
+ but also helps build interest, traffic and use of AJAX Chat.
+
+ Thanks,
+ Sebastian Tschan
+ //-->
+ <div id="copyright"><a href="https://blueimp.net/ajax/">AJAX Chat</a> &copy; <a href="https://blueimp.net">blueimp.net</a></div>
+ </div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/template/logs.html b/library/ajaxchat/chat/lib/template/logs.html
new file mode 100644
index 000000000..d0b9162a9
--- /dev/null
+++ b/library/ajaxchat/chat/lib/template/logs.html
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="[CONTENT_ENCODING/]"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="[LANG_CODE/]" lang="[LANG_CODE/]" dir="[BASE_DIRECTION/]">
+
+<head>
+ <meta http-equiv="Content-Type" content="[CONTENT_TYPE/]" />
+ <title>[LANG]logsTitle[/LANG]</title>
+ <style type="text/css">
+ body {
+ padding:0;
+ margin:0;
+ }
+ </style>
+ [STYLE_SHEETS/]
+ <!--[if lt IE 7]>
+ <link rel="stylesheet" type="text/css" href="css/ie5-6.css"/>
+ <script type="text/javascript">
+ var isIElt7 = true;
+ </script>
+ <![endif]-->
+ <script src="js/chat.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/logs.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/lang/[LANG_CODE/].js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/config.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="js/FABridge.js" type="text/javascript" charset="UTF-8"></script>
+ <script type="text/javascript">
+ // <![CDATA[
+ function toggleContainer(containerID, hideContainerIDs) {
+ if(hideContainerIDs) {
+ for(var i=0; i<hideContainerIDs.length; i++) {
+ ajaxChat.showHide(hideContainerIDs[i], 'none');
+ }
+ }
+ ajaxChat.showHide(containerID);
+ if(typeof arguments.callee.styleProperty == 'undefined') {
+ if(typeof isIElt7 != 'undefined') {
+ arguments.callee.styleProperty = 'marginRight';
+ } else {
+ arguments.callee.styleProperty = 'right';
+ }
+ }
+ var containerWidth = document.getElementById(containerID).offsetWidth;
+ if(containerWidth) {
+ document.getElementById('chatList').style[arguments.callee.styleProperty] = (containerWidth+28)+'px';
+ } else {
+ document.getElementById('chatList').style[arguments.callee.styleProperty] = '20px';
+ }
+ }
+
+ function initialize() {
+ toggleContainer('settingsContainer');
+ ajaxChat.updateButton('audio', 'audioButton');
+ ajaxChat.updateButton('autoScroll', 'autoScrollButton');
+ document.getElementById('bbCodeSetting').checked = ajaxChat.getSetting('bbCode');
+ document.getElementById('hyperLinksSetting').checked = ajaxChat.getSetting('hyperLinks');
+ document.getElementById('lineBreaksSetting').checked = ajaxChat.getSetting('lineBreaks');
+ document.getElementById('emoticonsSetting').checked = ajaxChat.getSetting('emoticons');
+ document.getElementById('autoFocusSetting').checked = ajaxChat.getSetting('autoFocus');
+ document.getElementById('maxMessagesSetting').value = ajaxChat.getSetting('maxMessages');
+ document.getElementById('wordWrapSetting').checked = ajaxChat.getSetting('wordWrap');
+ document.getElementById('maxWordLengthSetting').value = ajaxChat.getSetting('maxWordLength');
+ document.getElementById('dateFormatSetting').value = ajaxChat.getSetting('dateFormat');
+ document.getElementById('persistFontColorSetting').checked = ajaxChat.getSetting('persistFontColor');
+ for(var i=0; i<document.getElementById('audioVolumeSetting').options.length; i++) {
+ if(document.getElementById('audioVolumeSetting').options[i].value == ajaxChat.getSetting('audioVolume')) {
+ document.getElementById('audioVolumeSetting').options[i].selected = true;
+ break;
+ }
+ }
+ ajaxChat.fillSoundSelection('soundReceiveSetting', ajaxChat.getSetting('soundReceive'));
+ ajaxChat.fillSoundSelection('soundSendSetting', ajaxChat.getSetting('soundSend'));
+ ajaxChat.fillSoundSelection('soundEnterSetting', ajaxChat.getSetting('soundEnter'));
+ ajaxChat.fillSoundSelection('soundLeaveSetting', ajaxChat.getSetting('soundLeave'));
+ ajaxChat.fillSoundSelection('soundChatBotSetting', ajaxChat.getSetting('soundChatBot'));
+ ajaxChat.fillSoundSelection('soundErrorSetting', ajaxChat.getSetting('soundError'));
+ document.getElementById('blinkSetting').checked = ajaxChat.getSetting('blink');
+ document.getElementById('blinkIntervalSetting').value = ajaxChat.getSetting('blinkInterval');
+ document.getElementById('blinkIntervalNumberSetting').value = ajaxChat.getSetting('blinkIntervalNumber');
+ }
+
+ ajaxChatConfig.sessionName = '[SESSION_NAME/]';
+ ajaxChatConfig.cookieExpiration = parseInt('[COOKIE_EXPIRATION/]');
+ ajaxChatConfig.cookiePath = '[COOKIE_PATH/]';
+ ajaxChatConfig.cookieDomain = '[COOKIE_DOMAIN/]';
+ ajaxChatConfig.cookieSecure = '[COOKIE_SECURE/]';
+ ajaxChatConfig.chatBotName = decodeURIComponent('[CHAT_BOT_NAME/]');
+ ajaxChatConfig.chatBotID = '[CHAT_BOT_ID/]';
+ ajaxChatConfig.allowUserMessageDelete = parseInt('[ALLOW_USER_MESSAGE_DELETE/]');
+ ajaxChatConfig.inactiveTimeout = parseInt('[INACTIVE_TIMEOUT/]');
+ ajaxChatConfig.privateChannelDiff = parseInt('[PRIVATE_CHANNEL_DIFF/]');
+ ajaxChatConfig.privateMessageDiff = parseInt('[PRIVATE_MESSAGE_DIFF/]');
+ ajaxChatConfig.showChannelMessages = true;
+ ajaxChatConfig.messageTextMaxLength = parseInt('[MESSAGE_TEXT_MAX_LENGTH/]');
+ ajaxChatConfig.socketServerEnabled = parseInt('[SOCKET_SERVER_ENABLED/]');
+ ajaxChatConfig.socketServerHost = decodeURIComponent('[SOCKET_SERVER_HOST/]');
+ ajaxChatConfig.socketServerPort = parseInt('[SOCKET_SERVER_PORT/]');
+ ajaxChatConfig.socketServerChatID = parseInt('[SOCKET_SERVER_CHAT_ID/]');
+
+ ajaxChatConfig.ajaxURL += '&view=logs';
+
+ ajaxChatConfig.domIDs['yearSelection'] = 'yearSelection';
+ ajaxChatConfig.domIDs['monthSelection'] = 'monthSelection';
+ ajaxChatConfig.domIDs['daySelection'] = 'daySelection';
+ ajaxChatConfig.domIDs['hourSelection'] = 'hourSelection';
+
+ ajaxChatConfig.settings.dateFormat = '(%Y.%m.%d - %H:%i:%s)';
+ ajaxChatConfig.settings.audio = false;
+ ajaxChatConfig.settings.blink = false;
+ ajaxChatConfig.nonPersistentSettings.push('dateFormat','audio','blink');
+
+ ajaxChat.init(ajaxChatConfig, ajaxChatLang, true, true, true, initialize);
+ // ]]>
+ </script>
+</head>
+
+<body>
+ <div id="content">
+ <div id="headlineContainer">
+ <h1>[LANG]logsTitle[/LANG]</h1>
+ </div>
+ <div id="logoutChannelContainer">
+ <input type="button" id="logoutButton" value="[LANG]logout[/LANG]" onclick="ajaxChat.logout();"/>
+ <label for="channelSelection">[LANG]channel[/LANG]:</label>
+ <select id="channelSelection" onchange="ajaxChat.getLogs();">[LOGS_CHANNEL_OPTIONS/]</select>
+ <label for="yearSelection">[LANG]logsDate[/LANG]:</label>
+ <select id="yearSelection" onchange="ajaxChat.getLogs();">[LOGS_YEAR_OPTIONS/]</select>
+ <select id="monthSelection" onchange="ajaxChat.getLogs();">[LOGS_MONTH_OPTIONS/]</select>
+ <select id="daySelection" onchange="ajaxChat.getLogs();">[LOGS_DAY_OPTIONS/]</select>
+ <label for="hourSelection">[LANG]logsTime[/LANG]:</label>
+ <select id="hourSelection" onchange="ajaxChat.getLogs();">[LOGS_HOUR_OPTIONS/]</select>
+ <label for="styleSelection">[LANG]style[/LANG]:</label>
+ <select id="styleSelection" onchange="ajaxChat.setActiveStyleSheet(ajaxChat.getSelectedStyle());">[STYLE_OPTIONS/]</select>
+ <label for="languageSelection">[LANG]language[/LANG]:</label>
+ <select id="languageSelection" onchange="ajaxChat.switchLanguage(this.value);">[LANGUAGE_OPTIONS/]</select>
+ </div>
+ <!--[if lt IE 7]>
+ <div></div>
+ <![endif]-->
+ <div id="chatList"></div>
+ <div id="inputFieldContainer">
+ <textarea id="inputField" rows="1" cols="50" title="[LANG]inputLineBreak[/LANG]" onkeypress="ajaxChat.handleInputFieldKeyPress(event);"></textarea>
+ </div>
+ <div id="submitButtonContainer">
+ <input type="button" id="submitButton" value="[LANG]logsSearch[/LANG]" onclick="ajaxChat.sendMessage();"/>
+ </div>
+ <div id="optionsContainer">
+ <input type="image" src="img/pixel.gif" class="button" id="settingsButton" alt="[LANG]toggleSettings[/LANG]" title="[LANG]toggleSettings[/LANG]" onclick="toggleContainer('settingsContainer');"/>
+ <input type="image" src="img/pixel.gif" class="button" id="audioButton" alt="[LANG]toggleAudio[/LANG]" title="[LANG]toggleAudio[/LANG]" onclick="ajaxChat.toggleSetting('audio', 'audioButton');"/>
+ <input type="image" src="img/pixel.gif" class="button" id="autoScrollButton" alt="[LANG]toggleAutoScroll[/LANG]" title="[LANG]toggleAutoScroll[/LANG]" onclick="ajaxChat.toggleSetting('autoScroll', 'autoScrollButton')"/>
+ </div>
+ <div id="settingsContainer" style="display:none;">
+ <h3>[LANG]settings[/LANG]</h3>
+ <div id="settingsList">
+ <table>
+ <tr class="rowOdd">
+ <td><label for="bbCodeSetting">[LANG]settingsBBCode[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="bbCodeSetting" onclick="ajaxChat.setSetting('bbCode', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="hyperLinksSetting">[LANG]settingsHyperLinks[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="hyperLinksSetting" onclick="ajaxChat.setSetting('hyperLinks', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="lineBreaksSetting">[LANG]settingsLineBreaks[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="lineBreaksSetting" onclick="ajaxChat.setSetting('lineBreaks', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="emoticonsSetting">[LANG]settingsEmoticons[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="emoticonsSetting" onclick="ajaxChat.setSetting('emoticons', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="autoFocusSetting">[LANG]settingsAutoFocus[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="autoFocusSetting" onclick="ajaxChat.setSetting('autoFocus', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="maxMessagesSetting">[LANG]settingsMaxMessages[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="maxMessagesSetting" onchange="ajaxChat.setSetting('maxMessages', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="wordWrapSetting">[LANG]settingsWordWrap[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="wordWrapSetting" onclick="ajaxChat.setSetting('wordWrap', this.checked);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="maxWordLengthSetting">[LANG]settingsMaxWordLength[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="maxWordLengthSetting" onchange="ajaxChat.setSetting('maxWordLength', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="dateFormatSetting">[LANG]settingsDateFormat[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="dateFormatSetting" onchange="ajaxChat.setSetting('dateFormat', this.value);"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="persistFontColorSetting">[LANG]settingsPersistFontColor[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="persistFontColorSetting" onclick="ajaxChat.setPersistFontColor(this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="audioVolumeSetting">[LANG]settingsAudioVolume[/LANG]</label></td>
+ <td class="setting">
+ <select class="left" id="audioVolumeSetting" onchange="ajaxChat.setAudioVolume(this.options[this.selectedIndex].value);">
+ <option value="1.0">100 %</option>
+ <option value="0.9">90 %</option>
+ <option value="0.8">80 %</option>
+ <option value="0.7">70 %</option>
+ <option value="0.6">60 %</option>
+ <option value="0.5">50 %</option>
+ <option value="0.4">40 %</option>
+ <option value="0.3">30 %</option>
+ <option value="0.2">20 %</option>
+ <option value="0.1">10 %</option>
+ </select>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundReceiveSetting">[LANG]settingsSoundReceive[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundReceiveSetting" onchange="ajaxChat.setSetting('soundReceive', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundSendSetting">[LANG]settingsSoundSend[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundSendSetting" onchange="ajaxChat.setSetting('soundSend', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundEnterSetting">[LANG]settingsSoundEnter[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundEnterSetting" onchange="ajaxChat.setSetting('soundEnter', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundLeaveSetting">[LANG]settingsSoundLeave[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundLeaveSetting" onchange="ajaxChat.setSetting('soundLeave', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="soundChatBotSetting">[LANG]settingsSoundChatBot[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundChatBotSetting" onchange="ajaxChat.setSetting('soundChatBot', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="soundErrorSetting">[LANG]settingsSoundError[/LANG]</label></td>
+ <td class="setting">
+ <select id="soundErrorSetting" onchange="ajaxChat.setSetting('soundError', this.options[this.selectedIndex].value);"><option value="">-</option></select><input type="image" src="img/pixel.gif" class="button playback" alt="[LANG]playSelectedSound[/LANG]" title="[LANG]playSelectedSound[/LANG]" onclick="ajaxChat.playSound(this.previousSibling.options[this.previousSibling.selectedIndex].value);"/>
+ </td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="blinkSetting">[LANG]settingsBlink[/LANG]</label></td>
+ <td class="setting"><input type="checkbox" id="blinkSetting" onclick="ajaxChat.setSetting('blink', this.checked);"/></td>
+ </tr>
+ <tr class="rowOdd">
+ <td><label for="blinkIntervalSetting">[LANG]settingsBlinkInterval[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="blinkIntervalSetting" onchange="ajaxChat.setSetting('blinkInterval', parseInt(this.value));"/></td>
+ </tr>
+ <tr class="rowEven">
+ <td><label for="blinkIntervalNumberSetting">[LANG]settingsBlinkIntervalNumber[/LANG]</label></td>
+ <td class="setting"><input type="text" class="text" id="blinkIntervalNumberSetting" onchange="ajaxChat.setSetting('blinkIntervalNumber', parseInt(this.value));"/></td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <!--
+ Please retain the full copyright notice below including the link to blueimp.net.
+ This not only gives respect to the amount of time given freely by the developer
+ but also helps build interest, traffic and use of AJAX Chat.
+
+ Thanks,
+ Sebastian Tschan
+ //-->
+ <div id="copyright"><a href="https://blueimp.net/ajax/">AJAX Chat</a> &copy; <a href="https://blueimp.net">blueimp.net</a></div>
+ </div>
+ <div id="flashInterfaceContainer"></div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/library/ajaxchat/chat/lib/template/shoutbox.html b/library/ajaxchat/chat/lib/template/shoutbox.html
new file mode 100644
index 000000000..5f2de9981
--- /dev/null
+++ b/library/ajaxchat/chat/lib/template/shoutbox.html
@@ -0,0 +1,60 @@
+<div id="ajaxChatContent">
+ <script src="[AJAX_CHAT_URL/]js/chat.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="[AJAX_CHAT_URL/]js/custom.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="[AJAX_CHAT_URL/]js/shoutbox.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="[AJAX_CHAT_URL/]js/lang/[LANG_CODE/].js" type="text/javascript" charset="UTF-8"></script>
+ <script src="[AJAX_CHAT_URL/]js/config.js" type="text/javascript" charset="UTF-8"></script>
+ <script src="[AJAX_CHAT_URL/]js/FABridge.js" type="text/javascript" charset="UTF-8"></script>
+ <div id="ajaxChatChatList"></div>
+ <div id="ajaxChatInputFieldContainer" class="[CLASS_WRITEABLE/]">
+ <input id="ajaxChatInputField" type="text" maxlength="[MESSAGE_TEXT_MAX_LENGTH/]" onkeypress="ajaxChat.handleInputFieldKeyPress(event);"/>
+ </div>
+ <script type="text/javascript">
+ // <![CDATA[
+ ajaxChatConfig.ajaxURL = '[AJAX_CHAT_URL/]?ajax=true&shoutbox=true';
+ ajaxChatConfig.baseURL = '[AJAX_CHAT_URL/]';
+
+ ajaxChatConfig.sessionName = '[SESSION_NAME/]';
+ ajaxChatConfig.cookieExpiration = parseInt('[COOKIE_EXPIRATION/]');
+ ajaxChatConfig.cookiePath = '[COOKIE_PATH/]';
+ ajaxChatConfig.cookieDomain = '[COOKIE_DOMAIN/]';
+ ajaxChatConfig.cookieSecure = '[COOKIE_SECURE/]';
+ ajaxChatConfig.chatBotName = decodeURIComponent('[CHAT_BOT_NAME/]');
+ ajaxChatConfig.chatBotID = '[CHAT_BOT_ID/]';
+ ajaxChatConfig.allowUserMessageDelete = parseInt('[ALLOW_USER_MESSAGE_DELETE/]');
+ ajaxChatConfig.inactiveTimeout = parseInt('[INACTIVE_TIMEOUT/]');
+ ajaxChatConfig.privateChannelDiff = parseInt('[PRIVATE_CHANNEL_DIFF/]');
+ ajaxChatConfig.privateMessageDiff = parseInt('[PRIVATE_MESSAGE_DIFF/]');
+ ajaxChatConfig.showChannelMessages = false;
+ ajaxChatConfig.messageTextMaxLength = parseInt('[MESSAGE_TEXT_MAX_LENGTH/]');
+ ajaxChatConfig.socketServerEnabled = parseInt('[SOCKET_SERVER_ENABLED/]');
+ ajaxChatConfig.socketServerHost = decodeURIComponent('[SOCKET_SERVER_HOST/]');
+ ajaxChatConfig.socketServerPort = parseInt('[SOCKET_SERVER_PORT/]');
+ ajaxChatConfig.socketServerChatID = parseInt('[SOCKET_SERVER_CHAT_ID/]');
+
+ ajaxChatConfig.domIDs['chatList'] = 'ajaxChatChatList';
+ ajaxChatConfig.domIDs['inputField'] = 'ajaxChatInputField';
+ ajaxChatConfig.domIDs['flashInterfaceContainer'] = 'ajaxChatFlashInterfaceContainer';
+
+ ajaxChatConfig.startChatOnLoad = false;
+
+ ajaxChatConfig.settings.autoFocus = false;
+ ajaxChatConfig.settings.wordWrap = true;
+ ajaxChatConfig.settings.maxWordLength = 11;
+ ajaxChatConfig.settings.blink = false;
+ ajaxChatConfig.nonPersistentSettings.push('autoFocus','wordWrap','maxWordLength','blink');
+
+ ajaxChat.init(ajaxChatConfig, ajaxChatLang, true, false, true);
+ // ]]>
+ </script>
+ <!--
+ Please retain the full copyright notice below including the link to blueimp.net.
+ This not only gives respect to the amount of time given freely by the developer
+ but also helps build interest, traffic and use of AJAX Chat.
+
+ Thanks,
+ Sebastian Tschan
+ //-->
+ <div id="ajaxChatCopyright"><a href="https://blueimp.net/ajax/">AJAX Chat</a> &copy; <a href="https://blueimp.net">blueimp.net</a></div>
+</div>
+<div id="ajaxChatFlashInterfaceContainer"></div>
diff --git a/library/ajaxchat/chat/license.txt b/library/ajaxchat/chat/license.txt
new file mode 100644
index 000000000..618f9a318
--- /dev/null
+++ b/library/ajaxchat/chat/license.txt
@@ -0,0 +1,28 @@
+Modified MIT License (MIT)
+
+Copyright (c) 2013 blueimp.net
+
+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.
+
+The above license does not apply to files included in the AJAX Chat project
+which fall under other licenses. Such files are provided with their own
+license text included beside or within the files themselves.
+The presence of this modified MIT license in AJAX Chat does NOT supersede
+the licenses applying to those files. You many NOT redistribute this project
+or included files in a way that conflicts with their respective licenses. \ No newline at end of file
diff --git a/library/ajaxchat/chat/readme.html b/library/ajaxchat/chat/readme.html
new file mode 100644
index 000000000..145e188d3
--- /dev/null
+++ b/library/ajaxchat/chat/readme.html
@@ -0,0 +1,436 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>AJAX Chat Readme</title>
+
+ <style type="text/css">
+ body,td,th { font-family: Arial, Helvetica, sans-serif; line-height:1.6em; color:#000; font-size: inherit; }
+ body{background:#E7E7E7;margin:0; font-size: 0.8em;}
+ pre {font-size: 1.2em}
+ #wrap{max-width:1200px;background:#fff;margin:0.5em auto;padding:1.5em;box-shadow:2px 2px 4px #555;}
+ .subsection{border:1px solid #006;padding:0.8em 1.6em; background:#F2F5F9;}
+ .subsection .subsection{border:0}
+ a:link{color:#036;text-decoration:none}
+ a:visited{color:#03F;text-decoration:none}
+ td{padding:.5em}
+ .filename{color:#060}
+ .note{font-style:italic;background-color:#FFFFa9;border-radius:10px;padding:1em 1.2em}
+ a:hover{color:#03F;text-decoration:underline}
+ a:active{color:#03F;text-decoration:none;text-align:center}
+ h1,h2,h3,h4,h5,h6{font-weight:400;line-height:100%;margin:0; font-family: Verdana, Geneva, sans-serif;}
+ h1{font-size:1.8em;color:#E3E3FB;margin:-0.7em -0.7em 0.5em -0.7em;padding:0.8em; background: #2F2E8B; font-weight: 700;}
+ h2{font-size:1.3em;color:#FFF;background-color:#2F2E8B;clear:both;border-radius:5px 5px 0 0;margin:2em 0 0;padding:.5em}
+ h2:target{background-color:#6854E4;}
+ .version { font-size: 0.6em; font-weight: bold; line-height: 150%; display: block; }
+ .version a { color:#e4e4e4; text-decoration: underline;}
+ #toc{color:#000;background-color:#EBEBEB;display:block;float:right;width:20em;line-height:170%;border-radius:5px;border-color:#FFF;margin:0 0 1em 1em;padding:1.2em}
+ #toc h2{background:#333;color:#FFF;margin:-1em -1em 0.5em;padding:0.5em}
+ #toc ol{margin:0}
+ ol li{margin-bottom:1em}
+ h3{color:#000;background-color:#CED2DD;padding:.5em; font-weight: bold;border-radius:5px;}
+ code{display:block;background-color:#DDD;margin:1em;padding:1em; font-family: Consolas,"Liberation Mono",Courier,monospace;}
+ table{border:0}
+ th{font-weight:bold;vertical-align:middle;text-align:left;padding:.2em; }
+ p{margin:.5em 0}
+ #toc ol li,#toc p{margin:0;padding:0}
+ </style>
+</head>
+
+<body>
+<div id="wrap">
+
+<h1 id="top">AJAX Chat
+ <span class="version">
+ v 0.8.7 standalone ( <a href="https://blueimp.net/ajax/">blueimp.net/ajax/</a> )
+ </span>
+</h1>
+
+<div id="toc">
+ <h2>Table of Contents</h2>
+ <p><a href="#requirements">Requirements</a></p>
+ <p><a href="#installation">Installation</a></p>
+ <p><a href="#configuring">Configuring and Customizing</a></p>
+ <p><a href="#logs">Logs</a></p>
+ <p><a href="#shoutbox">Shoutbox</a></p>
+ <p><a href="#socket">Socket Server</a></p>
+ <p><a href="#support">Support</a></p>
+ <p><a href="#donate">Donate</a></p>
+ <p><a href="#license">License</a></p>
+</div>
+
+<p style="margin:1.5em">This is the <strong>standalone</strong> version of blueimp's AJAX Chat designed to run on its own, without another web application.<br>
+If you want to integrate AJAX Chat with one of the forums we support, go back and choose the right version. <br>
+This version is good for customizing your own integration, or using on its own.</p>
+
+<p class="note" style="margin-right: 30em;">
+ AJAX stands for &quot;Asynchronous JavaScript and XML&quot;.<br>
+ The AJAX Chat client (your browser) uses JavaScript to query the web server for updates.<br>
+ Instead of delivering a complete HTML page only updated data is sent in XML format.<br>
+ By using JavaScript the chat page can be updated without having to reload the whole page.<br>
+ PHP is used to communicate with the database and authenticate users.
+</p>
+
+<h2 id="requirements">Requirements</h2>
+<div class="subsection">
+ <table style="width: 550px;" summary="Requirements for running AJAX Chat.">
+ <tr>
+ <th width="275" scope="col">Server-Side</th>
+ <th width="275" scope="col">Client-Side</th>
+ </tr>
+ <tr>
+ <td>
+ PHP &gt;= 5<br>
+ MySQL &gt;= 4<br>
+ Ruby &gt;= 1.8 (optional)
+ </td>
+ <td>
+ Enabled JavaScript<br>
+ Enabled Cookies<br>
+ Flash Plugin &gt;= 9 (optional)
+ </td>
+ </tr>
+ </table>
+</div>
+
+<h2 id="installation">Installation</h2>
+<div class="subsection">
+ <p>Download your preferred version of AJAX Chat and unzip the file on your computer.<br></p>
+ <h3>Before You Begin</h3>
+ <div class="subsection">
+ <p>
+ In order to edit PHP files you will need a good text editor. <strong>You should not use Windows notepad, wordpad, or Microsoft Word to edit PHP files.</strong> These programs will add something called a byte-order-mark (BOM) to the files and this may prevent chat from functioning properly.
+ We recommend using Notepad ++ ( <a href="http://notepad-plus-plus.org/">http://notepad-plus-plus.org</a> ) for editing all files. It also has the benefit of color-coding your files so you can edit them more easily.<br>
+ If you get an error message like &quot;<strong>Cannot modify header information - headers already sent</strong>&quot; it is likely because you have used one of the above programs to edit files.
+ </p>
+ </div>
+
+ <h3>Configure Database Settings</h3>
+ <div class="subsection">
+ <p>
+ The first and most important thing you need to do is tell AJAX Chat how to connect to your database. This, and all core settings must be located inside the file <span class="filename">lib/config.php</span>. <br>
+ <strong>You need to create this file.</strong> <br>
+ An example <span class="filename">config.php</span> file can be found in <span class="filename">lib/config.php.example</span> that shipped with chat.<br>
+ Duplicate this file and save it as config.php (or just delete .example from the end of the file name) and then fill out at least the following four fields in the file:</p>
+ <p>
+ <code>$config['dbConnection']['host'] = '<em>your_database_hostname</em>';<br>
+ $config['dbConnection']['user'] = '<em>your_database_username</em>';<br>
+ $config['dbConnection']['pass'] = '<em>your_database_password</em>';<br>
+ $config['dbConnection']['name'] = '<em>your_database_name</em>';</code>
+ </p>
+ <p>Sufficed to say you need this information. Talk to your hosting provider if you don't know. </p>
+ <p>In most cases, chat will function with only these fields filled out and you can proceed to the next step.<br>
+ </p>
+ <p class="note">If your host does not use mysqli you will need to change the connection type field:<br>
+ $config['dbConnection']['type'] = null;<br>
+ If this is set to &quot;null&quot; it defaults to &quot;mysqli&quot; if existing, else to &quot;mysql&quot;. In most cases this field can be left as null.<br>
+ <br>
+ You can reference an existing database connection link or object by changing:<br>
+ $config['dbConnection']['link'] = null;<br>
+ If this is set to null, a new database connection is created.</p>
+ </div>
+
+ <h3>Choose Your Channel Settings</h3>
+ <div class="subsection">
+ <p>Edit the file <span class="filename">lib/data/channels.php.</span><br>
+ We have provided you with two sample channels, named public and private. You can add your own, or leave it as-is.<br>
+ Channels follow the following format:
+ <br>
+ <code>$channels[<em>channel id</em>] = '<em>channel name</em>';</code>
+ Each channel must have a unique channel id number and a unique name.<br>
+ Whitespace in the channel names will be converted to the underscore &quot;_&quot;.</p>
+ </div>
+
+ <h3>Add Your Users</h3>
+ <div class="subsection">
+ <p> Edit users in <span class="filename">lib/data/users.php</span>.<br>
+ Users follow the following format:
+ </p>
+ <p><code>$users[<em>user id</em>] = array();<br>
+ $users[<em>user id</em>]['userRole'] = <em>AJAX_CHAT_ROLE</em>;<br>
+ $users[<em>user id</em>]['userName'] = '<em>user name</em>';<br>
+ $users[<em>user id</em>]['password'] = '<em>user password</em>';<br>
+ $users[<em>user id</em>]['channels'] = array(<em>allowed channel ids</em>);</code><br>
+ Each user must have a unique user id number and a unique name.<br>
+ The first user in the list (user id 0) is used for the guest user settings. All guest users will have access to the channels set for this user and the user role AJAX_CHAT_GUEST.<br>
+ Registered users can have the user roles AJAX_CHAT_USER, AJAX_CHAT_MODERATOR or AJAX_CHAT_ADMIN. (this is case sensitive, type it exactly)<br>
+ The list of channels a user has access to can be set for each user individually. Channel id's are separated by commas. eg: array(0,1,23); allows channels 0, 1 and 23.<br>
+ Whitespace in the user names will be converted to the underscore &quot;_&quot;.</p>
+ </div>
+
+ <h3>Upload to Your Server</h3>
+ <div class="subsection">
+ <p>Upload the chat folder to your server somewhere under your document root:<br>
+ e.g. http://example.org/path/to/chat/</p>
+ </div>
+ <h3>Create the Database Tables</h3>
+ <div class="subsection">
+ <p>There are two options available to you to create the database. The first, and usually the easiest option, is to run the installation script included with AJAX Chat. Alternatively, you may use a database tool like PHPMyAdmin to manually create the tables.</p>
+ <ol>
+ <li> To use the installation script, visit the following URL in your browser:<br>
+ <span class="filename">http://example.org/path/to/chat/install.php</span><br>
+ Where
+ &quot;http://example.org/path/to/chat/&quot; is the real URL to your chat directory.</li>
+ <li>To install it manually using PHPMyAdmin or a similar tool, copy the contents of the <span class="filename">chat.sql</span> file and run it as a query.</li>
+ </ol>
+ <p>Either of these methods will create the tables your database needs to store chat messages and other information.</p>
+ </div>
+
+ <h3>Delete the Installation Script</h3>
+ <div class="subsection">
+ <p>Delete the file <span class="filename">install.php</span> from the chat directory on your server. You may also delete the file <span class="filename">chat.sql</span>.</p>
+ </div>
+
+ <h3>Congradulation! You Are Winner!</h3>
+ <div class="subsection">
+ <p>Yay! You're done! To test your chat, navigate to your chat URL in a browser: <span class="filename">http://example.org/path/to/chat/index.php<br>
+ </span>You are now free to customize chat to further suit your needs.</p>
+ </div>
+</div>
+
+<h2 id="configuring">Configuring and Customizing</h2>
+<div class="subsection">
+ <h3>Configuration Files</h3>
+ <div class="subsection">
+ <p>AJAX Chat is fully customizable and contains two configuration files:</p>
+ <ol>
+ <li><span class="filename">lib/config.php</span>: This file contains the core configuration options for chat. Essential options for configuring the database, security, available languages, etc, are found here.</li>
+ <li><span class="filename">js/config.js</span>: This file contains client side settings that change your users' default options in chat. Many of these settings can be changed by users in their options but some (like the refresh rate) cannot. </li>
+ </ol>
+ <p>Both of these files are well commented with information on what the settings mean.</p>
+ </div>
+
+ <h3>Customizing the Layout </h3>
+ <div class="subsection">
+ <p>The layout of AJAX Chat is fully customizable by using CSS (Cascaded Style Sheets).<br>
+ AJAX Chat comes with a predefined set of styles. To add your own style, do the following:</p>
+ <ol>
+ <li>Add a new CSS file (e.g. mystyle.css) by copying one of the existing styles from the CSS directory.</li>
+ <li>Edit your file (css/mystyle.css) and adjust the CSS settings to your liking.</li>
+ <li>Add the name of your style without file extension to the available styles in lib/config.php:<br>
+ <code>// Available styles: <br>
+ $config['styleAvailable'] = array('mystyle','beige','black','grey');<br>
+ // Default style:<br>
+ $config['styleDefault'] = 'mystyle';</code></li>
+ </ol>
+ <p>To further customize the layout you can adjust the template files in lib/template/.</p>
+ <p>Make sure you are creating valid XHTML, else you will produce errors in modern browsers.<br>
+ This is due to the page content-type served as &quot;application/xhtml+xml&quot;.<br>
+ Using this content-type improves performance when manipulating the Document Object Model (DOM).</p>
+ <p>If for some reason you cannot create valid XHTML you can force a HTML content-type.<br>
+ Just edit lib/config.php and set the following option:</p>
+ <p><code>$config['contentType'] = 'text/html';</code></p>
+ </div>
+
+ <h3>Adjusting the Language Settings</h3>
+ <div class="subsection">
+ <p>AJAX Chat comes with two language file directories:</p>
+ <ol>
+ <li><span class="filename">js/lang/</span>: This directory contains the language files used for the chat messages localization. These are JavaScript files with the extension &quot;.js&quot;.</li>
+ <li><span class="filename">lib/lang/</span>: This directory contains the language files used for the template output. These are PHP files with the extension &quot;.php&quot;.</li>
+ </ol>
+ <p>Many languages are already included with the download and you can customize them by editing these files.<br>
+ For each language, you need a file in both of these directories, with the language code as file name (such as en.js and en.php)..<br>
+ The language code is used following the ISO 639 standards.</p>
+ <p>The files for the english (language code &quot;en&quot;) localization are <span class="filename">js/lang/en.js</span> and <span class="filename">lib/lang/en.php</span>.</p>
+ <p>If you create your own localization, you must put the files in the correct folders and then make two changes to config.php:</p>
+ <ol>
+ <li>Add the language code (this must match the filename you chose for the language. Remember to use commas correctly to separate multiple language codes): <br>
+ <code>$config['langAvailable'] = array('en'); </code></li>
+ <li>Add the language name (this is what users see in the dropdown menu to choose the language): <br>
+ <code>$config['langNames'] = array('en'=&gt;'English');</code></li>
+ </ol>
+ <p>To avoid errors, you should follow these rules:</p>
+ <ol>
+ <li>Make sure you encode your localization files in UTF-8 (without Byte-order mark).</li>
+ <li>Don't use HTML entities in your localization files.</li>
+ <li>Don't remove any &quot;%s&quot; inside the JavaScript language files - these are filled with dynamic data. </li>
+ </ol>
+ </div>
+
+ <h3>Adding Features</h3>
+ <div class="subsection">
+ <p>AJAX Chat is designed with numerous hooks and overrides available to improve core functionality without requiring you to edit the core files.
+ With an intermediate understading of PHP and javascript you can modify your chat to suit your needs.</p>
+ <p>Have a look through a few examples available on the wiki:
+ <a href="https://github.com/Frug/AJAX-Chat/wiki/General-modifications">https://github.com/Frug/AJAX-Chat/wiki/General-modifications</a>
+ </p>
+ </div>
+
+</div>
+
+<h2 id="logs">Logs</h2>
+<div class="subsection">
+ <h3>Accessing the Logs</h3>
+ <div class="subsection">
+ <p>By default, AJAX Chat stores all chat messages in the database.<br>
+ To access the logs you have to add the GET parameter view=logs to your chat url (add ?view=logs to the end of the url):</p>
+ <p class="note">e.g. http://example.org/path/to/chat/?view=logs</p>
+ <p>If you are not already logged in, you have to login as administrator to access the logs.</p>
+ <p>The log view enables you to monitor the latest chat messages on all channels.<br>
+ It is also possible to view the logs of private rooms and private messages.<br>
+ You have the option to filter the logs by date, time and search strings.</p>
+ <p class="note">The search filter accepts MySQL style regular expressions as described here: <a href="http://dev.mysql.com/doc/refman/5.1/en/regexp.html">http://dev.mysql.com/doc/refman/5.1/en/regexp.html</a><br>
+ You can search for IPs, using the following syntax: ip=127.0.0.1</p>
+ </div>
+</div>
+
+<h2 id="shoutbox">Shoutbox</h2>
+<div class="subsection">
+ <p>AJAX Chat is also usable as shoutbox - this is a short guide on how to set it up:</p>
+
+ <h3>Shoutbox Stylesheet</h3>
+ <div class="subsection">
+ <p>Add the following line to the stylesheet (CSS) of all pages displaying the shoutbox:</p>
+ <p> <code>@import url(&quot;http://example.org/path/to/chat/css/shoutbox.css&quot;);</code></p>
+ <p> Replace http://example.org/path/to/chat/ with the URL to the chat.<br>
+ Modify css/shoutbox.css to your liking.</p>
+ </div>
+
+ <h3>Shoutbox Function</h3>
+ <div class="subsection">
+ <p>Add the following function to your PHP code:</p>
+
+<code><pre>
+&lt;?php
+function getShoutBoxContent() {
+// URL to the chat directory:
+if(!defined('AJAX_CHAT_URL')) {
+ define('AJAX_CHAT_URL', './chat/');
+}
+
+// Path to the chat directory:
+if(!defined('AJAX_CHAT_PATH')) {
+ define('AJAX_CHAT_PATH', realpath(dirname($_SERVER['SCRIPT_FILENAME']).'/chat').'/');
+}
+
+// Validate the path to the chat:
+if(@is_file(AJAX_CHAT_PATH.'lib/classes.php')) {
+
+ // Include Class libraries:
+ require_once(AJAX_CHAT_PATH.'lib/classes.php');
+
+ // Initialize the shoutbox:
+ $ajaxChat = new CustomAJAXChatShoutBox();
+
+ // Parse and return the shoutbox template content:
+ return $ajaxChat-&gt;getShoutBoxContent();
+}
+
+return null;
+}
+?&gt;
+</pre></code>
+
+ <p>Make sure AJAX_CHAT_URL and AJAX_CHAT_PATH point to the chat directory.</p>
+ </div>
+
+ <h3>Shoutbox Output</h3>
+ <div class="subsection">
+ <p>Display the shoutbox content using the shoutbox function:</p>
+ <p> <code>&lt;div style=&quot;width:200px;&quot;&gt;&lt;?php echo getShoutBoxContent(); ?&gt;&lt;/div&gt;</code></p>
+ </div>
+</div>
+
+<h2 id="socket">Socket Server</h2>
+<div class="subsection">
+ <p>Using the AJAX technology alone the chat clients have to permanently pull updates from the server.<br>
+ This is due to AJAX being a web technology and HTTP being a stateless protocol.<br>
+ Events pushed from server-side need a permanent or long-lasting socket connection between clients and server.<br>
+ This requires either a custom HTTP server (called &quot;comet&quot;) or another custom socket server.</p>
+ <p>AJAX Chat uses a JavaScript-to-Flash bridge to establish a permanent socket connection from client side.<br>
+ The JavaScript-to-Flash bridge requires a Flash plugin &gt;= 9 installed on the user browser.<br>
+ Clients without this requirement will fall back to pull the server for updates.</p>
+ <p class="note">This part of the setup is OPTIONAL and meant for experienced users only.</p>
+ <h3>Installation</h3>
+ <div class="subsection">
+ <p>The socket server coming with AJAX Chat is implemented in Ruby.<br>
+ You need to be able to run a Ruby script as a service to run the socket server.<br>
+ To be able to start the service, the script files in the socket/ directory have to be executable:</p>
+ <p> <code>$ chmod +x server<br>
+ $ chmod +x server.rb</code></p>
+ <p> &quot;server&quot; is a simple bash script to start and stop a service.<br>
+ &quot;server.rb&quot; is the ruby socket server script.<br>
+ &quot;server.conf&quot; is a configuration file - each setting is explained with a comment.</p>
+ <p> To start the service, execute the &quot;server&quot; script with the parameter &quot;start&quot;:</p>
+ <p> <code>$ ./server start</code></p>
+ <p> This will create two additional files:</p>
+ <p> &quot;server.pid&quot; contains the process id of the service.<br>
+ &quot;server.log&quot; is filled with the socket server log.</p>
+ <p> To monitor the socket server logs, you can use the &quot;tail&quot; command included in most GNU/Linux distributions:</p>
+ <p> <code>$ tail -f server.log</code></p>
+ <p> By default only errors and start/stop of the server are logged.<br>
+ To get more detailed logs configure the log level by editing the configuration file.</p>
+ <p> To stop the service, execute the &quot;server&quot; script with the parameter &quot;stop&quot;:</p>
+ <p> <code>$ ./server stop</code></p>
+ <p> If the socket server is running, you have to enable the following option in lib/config.php:</p>
+ <p> <code>$config['socketServerEnabled'] = true;</code><br>
+ <br>
+ This tells the server-side chat script to broadcast chat messages via the socket server.<br>
+ Chat clients will establish a permanent connection to the socket server to listen for chat messages.</p>
+ <p> By default only local clients (127.0.0.1,::1) may broadcast messages.<br>
+ Clients allowed to broadcast messages may also handle the channel authentication.<br>
+ If your socket server is running on another host you should set the broadcast_clients option to the chat server IP.</p>
+ <p> Using the socket server increases response time while improving server performance at the same time.</p>
+ </div>
+
+ <h3>Flash Permissions</h3>
+ <div class="subsection">
+ <p>
+ Since Flash 9.0.115.0 and all Flash 10 versions, permissions for creating sockets using Flash have changed.<br>
+ Now an explicit permission (using xml-syntax) is required for creating socket connections. <br>
+ In the current state, socket server won't work with the newest Flash versions. <br>
+ You will get a &quot;Flash security error&quot; in the browser.
+ </p>
+ <p>
+ A solution is to use a policy-files server which will listen to connections in port 843 in the server.<br>
+ Each time a client tries to connect to the chat, the Flash client will request the policy authorization to the server.<br>
+ The policy-files server is downloadable from http://ammonlauritzen.com/FlashPolicyService-09b.zip<br>
+ It works with FF3 and IE7 (not yet tested in other browsers).
+ </p>
+ <p> A more detailed explanation can be found here:</p>
+ <p> * <a href="http://ammonlauritzen.com/blog/2007/12/13/new-flash-security-policies/">http://ammonlauritzen.com/blog/2007/12/13/new-flash-security-policies/</a><br>
+ * <a href="http://ammonlauritzen.com/blog/2008/04/22/flash-policy-service-daemon/">http://ammonlauritzen.com/blog/2008/04/22/flash-policy-service-daemon/</a><br>
+ </p>
+ <p> Official Adobe documentation:</p>
+ <p> * <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html">http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security.html</a><br>
+ * <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html">http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html</a></p>
+ </div>
+ <p>&nbsp;</p>
+</div>
+
+<h2 id="support">Support</h2>
+<div class="subsection">
+ <p>
+ <b>Please do not email the devs with support questions.</b><br>
+ For further documentation and some examples, check out our <a href="https://github.com/Frug/AJAX-Chat/wiki">github wiki</a>.<br>
+ For general support questions use <a href="https://groups.google.com/forum/?#!forum/ajax-chat">our google group</a>.<br>
+ For specific bug reports and a list of pending issues view <a href="https://github.com/Frug/AJAX-Chat">our github project</a>.<br>
+ </p>
+</div>
+
+<h2 id="donate">Donate</h2>
+<div class="subsection">
+ <p>
+ Your donations contribute to the growth and development of this project and are always appreciated.<br>
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
+ <input type="hidden" name="cmd" value="_s-xclick">
+ <input type="hidden" name="hosted_button_id" value="PUMN737V7XKG8">
+ <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit">
+ <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
+ </form>
+ I'm on gittip at <a href="https://www.gittip.com/Frug/">https://www.gittip.com/Frug</a>
+ </p>
+</div>
+
+<h2 id="license">License</h2>
+<div class="subsection">
+ <p>Bluimp's AJAX Chat is released under a Modified MIT License.</p>
+ <p>You should also find this license included with your download of this project.</p>
+</div>
+
+<p align="center"><a href="#top">back to top</a></p>
+
+</div>
+</body>
+</html>
diff --git a/library/ajaxchat/chat/socket/.htaccess b/library/ajaxchat/chat/socket/.htaccess
new file mode 100644
index 000000000..91e386dc9
--- /dev/null
+++ b/library/ajaxchat/chat/socket/.htaccess
@@ -0,0 +1,4 @@
+AuthType Basic
+AuthName "Forbidden"
+AuthUserFile /dev/null
+require user nobody \ No newline at end of file
diff --git a/library/ajaxchat/chat/socket/server b/library/ajaxchat/chat/socket/server
new file mode 100644
index 000000000..806b5ef74
--- /dev/null
+++ b/library/ajaxchat/chat/socket/server
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+# Simple bash script to start and stop a service
+# Works without access to /var/run/ or ps and pidof commands
+#
+# Date:: Wed, 09 Jan 2008
+# Author:: Sebastian Tschan, https://blueimp.net
+# License:: GNU Affero General Public License
+
+
+SERVICE_TITLE=Service
+SERVICE_BASENAME=${0##*/}
+SERVICE_DIR=${0%/$SERVICE_BASENAME}
+SERVICE_COMMAND=$SERVICE_DIR/$SERVICE_BASENAME.rb
+SERVICE_CONFIG=$SERVICE_DIR/$SERVICE_BASENAME.conf
+SERVICE_LOG=$SERVICE_DIR/$SERVICE_BASENAME.log
+SERVICE_PIDFILE=$SERVICE_DIR/$SERVICE_BASENAME.pid
+
+
+function start
+{
+ if [ -f $SERVICE_PIDFILE ]
+ then
+ echo "PID file $SERVICE_PIDFILE found - $SERVICE_TITLE already running?"
+ else
+ $SERVICE_COMMAND $SERVICE_CONFIG >> $SERVICE_LOG & echo "Started $SERVICE_TITLE..."
+ PID=$!
+ echo $PID > $SERVICE_PIDFILE
+ fi
+ exit 0
+}
+
+function stop
+{
+ if [ -f $SERVICE_PIDFILE ]
+ then
+ PID=`cat $SERVICE_PIDFILE`
+ kill -TERM $PID
+ rm -f $SERVICE_PIDFILE
+ echo "Stopped $SERVICE_TITLE."
+ else
+ echo "PID file $SERVICE_PIDFILE not found - $SERVICE_TITLE not running?"
+ fi
+ exit 0
+}
+
+function main
+{
+ for arg in $@
+ do
+ if [ $arg == "start" ]
+ then
+ start
+ elif [ $arg == "stop" ]
+ then
+ stop
+ else
+ echo "Unknown argument:" $arg
+ echo "Usage: $0 [start|stop]"
+ exit 0
+ fi
+ done
+
+ echo "Missing argument."
+ echo "Usage: $0 [start|stop]"
+ exit 0
+}
+
+
+# Script execution:
+main $@ \ No newline at end of file
diff --git a/library/ajaxchat/chat/socket/server.conf b/library/ajaxchat/chat/socket/server.conf
new file mode 100644
index 000000000..47c6849da
--- /dev/null
+++ b/library/ajaxchat/chat/socket/server.conf
@@ -0,0 +1,22 @@
+
+# Server address (leave empty to bind to all available interfaces):
+server_address=
+
+# Server port:
+server_port=1935
+
+# Comma-separated list of clients allowed to broadcast (allows all if empty):
+broadcast_clients=127.0.0.1,::1
+
+# Maximum number of clients (0 allows an unlimited number of clients):
+max_clients=0
+
+# Comma-separated list of domains from which downloaded Flash clients are allowed to connect (* allows all domains):
+allow_access_from=*
+
+# Log level:
+# 0 = log only errors and server start/stop
+# 1 = log client connections
+# 2 = log all messages but no broadcast content
+# 3 = log everything
+log_level=0
diff --git a/library/ajaxchat/chat/socket/server.rb b/library/ajaxchat/chat/socket/server.rb
new file mode 100644
index 000000000..c2f532c84
--- /dev/null
+++ b/library/ajaxchat/chat/socket/server.rb
@@ -0,0 +1,400 @@
+#!/usr/bin/env ruby
+
+# Simple Ruby XML Socket Server
+#
+# This is a a simple socket server implementation in ruby
+# to communicate with flash clients via Flash XML Sockets.
+#
+# The socket code is based on the tutorial
+# "Sockets programming in Ruby"
+# by M. Tim Jones (mtj@mtjones.com).
+#
+# Date:: Tue, 05 Mar 2008
+# Author:: Sebastian Tschan, https://blueimp.net
+# License:: GNU Affero General Public License
+
+# Include socket library:
+require 'socket'
+# Include XML libraries:
+require 'rexml/document'
+require 'rexml/streamlistener'
+
+# XML Stream Handler class used to parse chat messages:
+class XMLStreamHandler
+ attr_reader :type,:chat_id,:user_id,:reg_id,:channel_id,:channel_ids
+ # Called when an opening tag (including attributes) is parsed:
+ def tag_start name, attrs
+ case name
+ when 'root'
+ # root messages are broadcast messages:
+ @type = :message
+ @chat_id = attrs['chatID']
+ @channel_id = attrs['channelID']
+ throw :break
+ when 'register'
+ # register messages are sent by chat clients:
+ @type = :register
+ @chat_id = attrs['chatID']
+ @user_id = attrs['userID']
+ @reg_id = attrs['regID']
+ throw :break
+ when 'authenticate'
+ # authenticate messages are sent by the chat server client:
+ @type = :authenticate
+ @chat_id = attrs['chatID']
+ @user_id = attrs['userID']
+ @reg_id = attrs['regID']
+ @channel_ids = Array::new
+ when 'channel'
+ # authenticate messages contain channel tags:
+ if @channel_ids
+ @channel_ids.push(attrs['id'])
+ else
+ throw :break
+ end
+ when 'policy-file-request'
+ # policy-file-requests are sent by flash clients for cross-domain authentication:
+ @type = :policy_file_request
+ throw :break
+ else
+ throw :break
+ end
+ end
+ # Called when a closing tag is parsed:
+ def tag_end name
+ if name == 'authenticate'
+ throw :break
+ end
+ end
+ def text text
+ # Called on text between tags
+ end
+ # Called when cdata is parsed:
+ alias cdata text
+end
+
+# Socket Server class:
+class SocketServer
+
+ def initialize(config_file)
+ # List of configuration settings:
+ @config = Hash::new
+ # Initialize default settings:
+ initialize_default_properties
+ if config_file
+ # Load settings from configuration file:
+ load_properties_from_file(config_file)
+ end
+ # Sockets list:
+ @sockets = Array::new
+ # Clients list:
+ @clients = Hash::new
+ # Chats list, used to distinguish between different chat installations (contains channels list):
+ @chats = Hash::new
+ # Initialize server socket:
+ initialize_server_socket
+ if @server_socket
+ # Log server start (STDOUT.flush prevents output buffering):
+ puts "#{Time.now}\tServer started on Port #{@config[:server_port].to_s} ..."; STDOUT.flush
+ begin
+ # Start the server:
+ run
+ rescue SignalException
+ # Controlled stop:
+ ensure
+ for socket in @sockets
+ if socket != @server_socket
+ # Disconnect all clients:
+ handle_client_disconnection(socket, false)
+ end
+ end
+ @sockets = nil
+ @clients = nil
+ # Log server stop:
+ puts "#{Time.now}\tServer stopped."; STDOUT.flush
+ end
+ end
+ end
+
+ def run
+ # Endless loop:
+ while 1
+ # Blocking select call. The first three parameters are arrays of IO objects or nil.
+ # The last parameter is to set a timeout in seconds to force select to return
+ # if no event has occurred on any of the given IO object arrays.
+ res = select(@sockets, nil, nil, nil)
+ if res != nil then
+ # Iterate through the tagged read descriptors:
+ for socket in res[0]
+ # Received a connect to the server socket:
+ if socket == @server_socket then
+ accept_new_connection
+ else
+ # Received something on a client socket:
+ if socket.eof? then
+ # Handle client disconnection:
+ handle_client_disconnection(socket)
+ else
+ # Handle client input data:
+ handle_client_input(socket, socket.gets(@config[:eol]))
+ end
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def initialize_default_properties
+ # Server address (empty = bind to all available interfaces):
+ @config[:server_address] = ''
+ # Server port:
+ @config[:server_port] = 1935
+ # Comma-separated list of clients allowed to broadcast (allows all if empty):
+ @config[:broadcast_clients] = ''
+ # Defines if broadcast is sent to broadcasting client:
+ @config[:broadcast_self] = false
+ # Maximum number of clients (0 allows an unlimited number of clients):
+ @config[:max_clients] = 0
+ # Comma-separated list of domains from which downloaded Flash clients are allowed to connect (* allows all domains):
+ @config[:allow_access_from] = '*'
+ # Defines the cross-domain-policy string sent to Flash clients as response to a policy-file-request:
+ @config[:cross_domain_policy] = '<cross-domain-policy><allow-access-from domain="'+@config[:allow_access_from]+'" to-ports="'+@config[:server_port].to_s+'"/></cross-domain-policy>'
+ # EOL (End Of Line) character used by Flash XML Socket communication (a null-byte):
+ @config[:eol] = "\0"
+ # Log level (0 logs only errors and server start/stop, 1 logs client connections, 2 logs all messages but no broadcast content, 3 logs everything):
+ @config[:log_level] = 0
+ end
+
+ def load_properties_from_file(config_file)
+ # Open the config file and go through each line:
+ File.open(config_file, 'r') do |file|
+ file.read.each_line do |line|
+ # Remove trailing whitespace from the line:
+ line.strip!
+ # Get the position of the first "=":
+ i = line.index('=')
+ # Check if line is not a comment and a valid property:
+ if (!line.empty? && line[0] != ?# && i > 0)
+ # Add the configuration option to the config hash:
+ key = line[0..i - 1].strip
+ value = line[i + 1..-1].strip
+ # Parse boolean values:
+ if value.eql?('false')
+ @config[key.to_sym] = false
+ elsif value.eql?('true')
+ @config[key.to_sym] = true
+ # Parse integer numbers:
+ elsif value.to_i.to_s.eql?(value)
+ @config[key.to_sym] = value.to_i
+ # Parse floating point numbers:
+ elsif value.to_f.to_s.eql?(value)
+ @config[key.to_sym] = value.to_f
+ # Parse string values:
+ else
+ @config[key.to_sym] = value
+ end
+ end
+ end
+ end
+ if @config[:eol].empty?
+ # Use default EOL if configuration option is empty:
+ @config[:eol] = $/
+ end
+ end
+
+ def initialize_server_socket
+ begin
+ # The server socket, allowing connections from any interface and bound to the given port number:
+ @server_socket = TCPServer.new(@config[:server_address], @config[:server_port].to_i)
+ # Enable reuse of the server address (e.g. for rapid restarts of the server):
+ @server_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
+ # Add the server socket to the sockets list:
+ @sockets.push(@server_socket)
+ rescue Exception => error
+ # Log initialization failure:
+ puts "#{Time.now}\tFailed to initialize Server on Port #{@config[:server_port].to_s}: #{error}."; STDOUT.flush
+ end
+ end
+
+ def accept_new_connection
+ begin
+ # Accept the client connection (non-blocking):
+ socket = @server_socket.accept_nonblock
+ # Retrieve IP and Port:
+ ip = socket.peeraddr[3]
+ port = socket.peeraddr[1]
+ # Check if we have reached the maximum number of connected clients (always accept the broadcast clients):
+ if @config[:max_clients].to_i == 0 || @clients.size < @config[:max_clients].to_i || !@config[:broadcast_clients].empty? && @config[:broadcast_clients].include?(ip)
+ # Add the accepted socket connection to the socket list:
+ @sockets.push(socket)
+ # Create a new Hash to store the client data:
+ client = Hash::new
+ client[:id] = "[#{ip}]:#{port}"
+ # Check if the client is allowed to broadcast:
+ if @config[:broadcast_clients].empty? || @config[:broadcast_clients].include?(ip)
+ client[:allowed_to_broadcast] = true
+ else
+ client[:allowed_to_broadcast] = false
+ end
+ # Add the client to the clients list:
+ @clients[socket] = client
+ if @config[:log_level].to_i > 0
+ # Log client connection and the number of connected clients:
+ puts "#{Time.now}\t#{client[:id]} Connects\t(#{@clients.size} connected)"; STDOUT.flush
+ end
+ else
+ # Close the socket connection:
+ socket.close
+ end
+ rescue
+ # Client disconnected before the address information (IP, Port) could be retrieved.
+ end
+ end
+
+ def handle_client_disconnection(client_socket, delete_socket=true)
+ # Retrieve the client ID for the current socket:
+ client_id = @clients[client_socket][:id]
+ begin
+ # Close the socket connection:
+ client_socket.close
+ rescue
+ # Rescue if closing the socket fails
+ end
+ if delete_socket
+ # Remove the socket from the sockets list:
+ @sockets.delete(client_socket)
+ end
+ # Remove the client ID from the clients list:
+ @clients.delete(client_socket)
+ if @config[:log_level].to_i > 0
+ # Log client disconnection and the number of connected clients:
+ puts "#{Time.now}\t#{client_id} Disconnects\t(#{@clients.size} connected)"; STDOUT.flush
+ end
+ end
+
+ def handle_client_input(client_socket, str)
+ # Create a new XML stream handler:
+ handler = XMLStreamHandler.new
+ begin
+ # As soon as the parser has found the relevant information it throws a :break symbol:
+ catch :break do
+ # Parse the given input string for XML messages:
+ REXML::Document.parse_stream(str, handler)
+ end
+ # The handler stores a type property to define the parsed XML message:
+ case handler.type
+ when :message
+ handle_broadcast_message(client_socket, handler.chat_id, handler.channel_id, str)
+ when :register
+ handle_client_registration(client_socket, handler.chat_id, handler.user_id, handler.reg_id)
+ when :authenticate
+ handle_client_authentication(client_socket, handler.chat_id, handler.user_id, handler.reg_id, handler.channel_ids)
+ when :policy_file_request
+ handle_policy_file_request(client_socket)
+ end
+ rescue Exception => error
+ # Rescue if parsing the client input fails and log the error message:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Client Input Error:#{error.to_s.dump}"; STDOUT.flush
+ end
+ end
+
+ def handle_broadcast_message(client_socket, chat_id, channel_id, str)
+ # Check if the_client is allowed to broadcast:
+ if @clients[client_socket][:allowed_to_broadcast]
+ # Check if the chat and channel have been registered:
+ if @chats[chat_id] && (@chats[chat_id][channel_id] || @chats[chat_id]['ALL'])
+ # Go through the sockets list:
+ @sockets.each do |socket|
+ # Skip the server socket and skip the the client socket if broadcast is not to be sent to self:
+ if socket != @server_socket && (@config[:broadcast_self] || socket != client_socket)
+ # Only write to clients registered to the given channel or to the "ALL" channel:
+ if @chats[chat_id]['ALL']
+ reg_id = @chats[chat_id]['ALL'][@clients[socket][:user_id]]
+ end
+ if !reg_id && @chats[chat_id][channel_id]
+ reg_id = @chats[chat_id][channel_id][@clients[socket][:user_id]]
+ end
+ # Check if the reg_id stored for the given channel and user_id matches the clients reg_id:
+ if reg_id && reg_id.eql?(@clients[socket][:reg_id])
+ begin
+ # Write the broadcast message on the socket connection:
+ socket.write(str)
+ rescue
+ # Rescue if writing to the socket fails
+ end
+ end
+ end
+ end
+ end
+ if @config[:log_level].to_i > 2
+ # Log the message sent by the broadcast client:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Chat:#{chat_id.to_s.dump} Channel:#{channel_id.to_s.dump} Message:#{str.to_s.dump}"; STDOUT.flush
+ elsif @config[:log_level].to_i > 1
+ # Log the message sent by the broadcast client:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Chat:#{chat_id.to_s.dump} Channel:#{channel_id.to_s.dump} Message"; STDOUT.flush
+ end
+ end
+ end
+
+ def handle_client_registration(client_socket, chat_id, user_id, reg_id)
+ # Save the chat_id, use_id and reg_id as client properties:
+ @clients[client_socket][:chat_id] = chat_id
+ @clients[client_socket][:user_id] = user_id
+ @clients[client_socket][:reg_id] = reg_id
+ if @config[:log_level].to_i > 1
+ # Log the client registration:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Chat:#{chat_id.to_s.dump} User:#{user_id.to_s.dump} Reg:#{reg_id.to_s.dump}"; STDOUT.flush
+ end
+ end
+
+ def handle_client_authentication(client_socket, chat_id, user_id, reg_id, channel_ids)
+ # Only the broadcast clients may send authentication messages:
+ if @clients[client_socket][:allowed_to_broadcast]
+ # Create a new chat item if not found for the given chat_id:
+ if !@chats[chat_id]
+ @chats[chat_id] = Hash.new
+ end
+ # Go through the list of channels for the given chat:
+ @chats[chat_id].each_key do |key|
+ # Delete all items for the given user on all channels of the given chat:
+ @chats[chat_id][key].delete(user_id)
+ # If the chat channel is empty, delete the channel item:
+ if @chats[chat_id][key].size == 0
+ @chats[chat_id].delete(key)
+ end
+ end
+ # Go through the list of authenticated channel_ids:
+ channel_ids.each do |channel_id|
+ # Create a new channel item if not found for the current channel_id (and the given chat_id):
+ if !@chats[chat_id][channel_id]
+ @chats[chat_id][channel_id] = Hash.new
+ end
+ # Add a user item of the given user_id with the given reg_id to the current channel:
+ @chats[chat_id][channel_id][user_id] = reg_id
+ end
+ if @config[:log_level].to_i > 1
+ # Log the client authentication:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Chat:#{chat_id.to_s.dump} User:#{user_id.to_s.dump} Auth:#{reg_id.to_s.dump} Channels:#{channel_ids.join(',').dump}"; STDOUT.flush
+ end
+ end
+ end
+
+ def handle_policy_file_request(client_socket)
+ begin
+ # Write the cross-domain-policy to the Flash client:
+ client_socket.write(@config[:cross_domain_policy]+@config[:eol])
+ rescue
+ # Rescue if writing to the socket fails
+ end
+ if @config[:log_level].to_i > 1
+ # Log the policy-file-request:
+ puts "#{Time.now}\t#{@clients[client_socket][:id]} Policy-File-Request"; STDOUT.flush
+ end
+ end
+
+end
+
+# Start the socket server with the first command line argument as configuration file:
+SocketServer.new($*[0]) \ No newline at end of file
diff --git a/library/ajaxchat/chat/sounds/index.html b/library/ajaxchat/chat/sounds/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/index.html
diff --git a/library/ajaxchat/chat/sounds/license.txt b/library/ajaxchat/chat/sounds/license.txt
new file mode 100644
index 000000000..d4a756fe8
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/license.txt
@@ -0,0 +1,28 @@
+The sounds used for this project have been created by
+
+====================================
+Stuart Duffield (Soundsnap.com user)
+====================================
+
+http://soundsnap.com/user/21
+
+
+The sounds are licensed under the
+
+=================
+Soundsnap Licence
+=================
+
+http://soundsnap.com/licence
+
+You are Free:
+
+* To remix or transform the sounds in any way
+* To copy, distribute and transmit the sounds
+* To use the sounds in any music, film, video game, website etc.
+whether commercial or not, without paying royalties or other fees
+
+You Cannot:
+
+* Make commercial distribution of these sounds 'as they are'.
+For example, you cannot download and sell them as part of a CD library \ No newline at end of file
diff --git a/library/ajaxchat/chat/sounds/sound_1.mp3 b/library/ajaxchat/chat/sounds/sound_1.mp3
new file mode 100644
index 000000000..f9526e1ca
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_1.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/sounds/sound_2.mp3 b/library/ajaxchat/chat/sounds/sound_2.mp3
new file mode 100644
index 000000000..73bdcd2b1
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_2.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/sounds/sound_3.mp3 b/library/ajaxchat/chat/sounds/sound_3.mp3
new file mode 100644
index 000000000..1c765773a
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_3.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/sounds/sound_4.mp3 b/library/ajaxchat/chat/sounds/sound_4.mp3
new file mode 100644
index 000000000..d2f66baff
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_4.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/sounds/sound_5.mp3 b/library/ajaxchat/chat/sounds/sound_5.mp3
new file mode 100644
index 000000000..0d5a5f299
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_5.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/sounds/sound_6.mp3 b/library/ajaxchat/chat/sounds/sound_6.mp3
new file mode 100644
index 000000000..df6007948
--- /dev/null
+++ b/library/ajaxchat/chat/sounds/sound_6.mp3
Binary files differ
diff --git a/library/ajaxchat/chat/src/EmptySwf.as b/library/ajaxchat/chat/src/EmptySwf.as
new file mode 100644
index 000000000..373c5e375
--- /dev/null
+++ b/library/ajaxchat/chat/src/EmptySwf.as
@@ -0,0 +1,32 @@
+/*
+Copyright 2006 Adobe Systems Incorporated
+
+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.
+
+*/
+
+package {
+ import flash.display.MovieClip;
+ import bridge.FABridge;
+
+ public class EmptySwf extends MovieClip {
+
+ private var externalBridge:FABridge;
+
+ public function EmptySwf() {
+ super();
+ externalBridge = new FABridge();
+ externalBridge.rootObject = this;
+ }
+ }
+}
diff --git a/library/ajaxchat/chat/src/FABridge.as b/library/ajaxchat/chat/src/FABridge.as
new file mode 100644
index 000000000..d03dba01a
--- /dev/null
+++ b/library/ajaxchat/chat/src/FABridge.as
@@ -0,0 +1,943 @@
+/*
+Copyright � 2006 Adobe Systems Incorporated
+
+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.
+
+*/
+
+
+/*
+ * The Bridge class, responsible for navigating JS instances
+ */
+package bridge
+{
+
+/*
+ * imports
+ */
+import flash.external.ExternalInterface;
+import flash.utils.Timer;
+import flash.events.*;
+import flash.display.DisplayObject;
+import flash.system.ApplicationDomain;
+import flash.utils.Dictionary;
+import flash.utils.setTimeout;
+
+import mx.collections.errors.ItemPendingError;
+import mx.core.IMXMLObject;
+
+import flash.utils.getQualifiedClassName;
+import flash.utils.describeType;
+import flash.events.TimerEvent;
+
+/**
+ * The FABridge class, responsible for proxying AS objects into javascript
+ */
+public class FABridge extends EventDispatcher implements IMXMLObject
+{
+
+ //holds a list of stuff to call later, to break the recurrence of the js <> as calls
+ //you must use the full class name, as returned by the getQualifiedClassName() function
+ public static const MethodsToCallLater:Object = new Object();
+ MethodsToCallLater["mx.collections::ArrayCollection"]="refresh,removeItemAt";
+
+ public static const EventsToCallLater:Object = new Object();
+ EventsToCallLater["mx.data.events::UnresolvedConflictsEvent"]="true";
+ EventsToCallLater["mx.events::PropertyChangeEvent"]="true";
+
+ public static const INITIALIZED:String = "bridgeInitialized";
+
+ // constructor
+ public function FABridge()
+ {
+ super();
+ initializeCallbacks();
+ }
+
+ // private vars
+
+ /**
+ * stores a cache of descriptions of AS types suitable for sending to JS
+ */
+ private var localTypeMap:Dictionary = new Dictionary();
+
+ /**
+ * stores an id-referenced dictionary of objects exported to JS
+ */
+ private var localInstanceMap:Dictionary = new Dictionary();
+
+ /**
+ * stores an id-referenced dictionary of functions exported to JS
+ */
+ private var localFunctionMap:Dictionary = new Dictionary();
+
+ /**
+ * stores an id-referenced dictionary of proxy functions imported from JS
+ */
+ private var remoteFunctionCache:Dictionary = new Dictionary();
+
+ /**
+ * stores a list of custom serialization functions
+ */
+ private var customSerializersMap:Dictionary = new Dictionary();
+
+ /**
+ * stores a map of object ID's and their reference count
+ */
+ private var refMap:Dictionary = new Dictionary();
+ /**
+ * a local counter for generating unique IDs
+ */
+ private var nextID:Number = 0;
+
+ private var lastRef:int;
+
+ /* values that can't be serialized natively across the bridge are packed and identified by type.
+ These constants represent different serialization types */
+ public static const TYPE_ASINSTANCE:uint = 1;
+ public static const TYPE_ASFUNCTION:uint = 2;
+ public static const TYPE_JSFUNCTION:uint = 3;
+ public static const TYPE_ANONYMOUS:uint = 4;
+
+ private var _initChecked:Boolean = false;
+
+ // properties
+
+ //getters and setters for the main component in the swf - the root
+ public function get rootObject():DisplayObject {return _rootObject;}
+ public function set rootObject(value:DisplayObject):void
+ {
+ _rootObject = value;
+ checkInitialized();
+ }
+
+ /**
+ * the bridge name
+ */
+ public var bridgeName:String;
+ private var _registerComplete:Boolean = false;
+
+ /**
+ * increment the reference count for an object being passed over the bridge
+ */
+ public function incRef(objId:int):void
+ {
+ if(refMap[objId] == null) {
+ //the object is being created; we now add it to the map and set its refCount = 1
+ refMap[objId] = 1;
+ } else {
+ refMap[objId] = refMap[objId] +1;
+ }
+ }
+
+ /**
+ * when an object has been completely passed to JS its reference count is decreased with 1
+ */
+ public function releaseRef(objId:int):void
+ {
+ if(refMap[objId] != null)
+ {
+ var newRefVal:int = refMap[objId] - 1;
+ // if the object exists in the referenceMap and its count equals or has dropped under 0 we clean it up
+ if(refMap[objId] != null && newRefVal <= 0)
+ {
+ delete refMap[objId];
+ delete localInstanceMap[objId];
+ }
+ else
+ {
+ refMap[objId] = newRefVal;
+ }
+ }
+ }
+
+ /**
+ * attaches the callbacks to external interface
+ */
+ public function initializeCallbacks():void
+ {
+ if (ExternalInterface.available == false)
+ {
+ return;
+ }
+
+ ExternalInterface.addCallback("getRoot", js_getRoot);
+ ExternalInterface.addCallback("getPropFromAS", js_getPropFromAS);
+ ExternalInterface.addCallback("setPropInAS", js_setPropertyInAS);
+ ExternalInterface.addCallback("invokeASMethod", js_invokeMethod);
+ ExternalInterface.addCallback("invokeASFunction", js_invokeFunction);
+ ExternalInterface.addCallback("releaseASObjects", js_releaseASObjects);
+ ExternalInterface.addCallback("create", js_create);
+ ExternalInterface.addCallback("releaseNamedASObject",js_releaseNamedASObject);
+ ExternalInterface.addCallback("incRef", incRef);
+ ExternalInterface.addCallback("releaseRef", releaseRef);
+ }
+
+ private var _rootObject:DisplayObject;
+
+ private var _document:DisplayObject;
+
+ /**
+ * called to check whether the bridge has been initialized for the specified document/id pairs
+ */
+ public function initialized(document:Object, id:String):void
+ {
+ _document = (document as DisplayObject);
+
+ if (_document != null)
+ {
+ checkInitialized();
+ }
+ }
+
+ private function get baseObject():DisplayObject
+ {
+ return (rootObject == null)? _document:rootObject;
+ }
+
+
+ private function checkInitialized():void
+ {
+ if(_initChecked== true)
+ {
+ return;
+ }
+ _initChecked = true;
+
+ // oops! timing error. Player team is working on it.
+ var t:Timer = new Timer(200,1);
+ t.addEventListener(TimerEvent.TIMER,auxCheckInitialized);
+ t.start();
+ }
+
+ /**
+ * auxiliary initialization check that is called after the timing has occurred
+ */
+ private function auxCheckInitialized(e:Event):void
+ {
+
+ var bCanGetParams:Boolean = true;
+
+ try
+ {
+ var params:Object = baseObject.root.loaderInfo.parameters;
+ }
+ catch (e:Error)
+ {
+ bCanGetParams = false;
+ }
+
+ if (bCanGetParams == false)
+ {
+ var t:Timer = new Timer(100);
+ var timerFunc:Function = function(e:TimerEvent):void
+ {
+ if(baseObject.root != null)
+ {
+ try
+ {
+ bCanGetParams = true;
+ var params:Object = baseObject.root.loaderInfo.parameters;
+ }
+ catch (err:Error)
+ {
+ bCanGetParams = false;
+ }
+ if (bCanGetParams)
+ {
+ t.removeEventListener(TimerEvent.TIMER, timerFunc);
+ t.stop();
+ dispatchInit();
+ }
+ }
+ }
+ t.addEventListener(TimerEvent.TIMER, timerFunc);
+ t.start();
+ }
+ else
+ {
+ dispatchInit();
+ }
+ }
+
+ /**
+ * call into JS to annunce that the bridge is ready to be used
+ */
+ private function dispatchInit(e:Event = null):void
+ {
+ if(_registerComplete == true)
+ {
+ return;
+ }
+
+ if (ExternalInterface.available == false)
+ {
+ return;
+ }
+
+ if (bridgeName == null)
+ {
+ bridgeName = baseObject.root.loaderInfo.parameters["bridgeName"];
+
+ if(bridgeName == null)
+ {
+ bridgeName = "flash";
+ }
+ }
+
+ _registerComplete = ExternalInterface.call("FABridge__bridgeInitialized", [bridgeName]);
+ dispatchEvent(new Event(FABridge.INITIALIZED));
+ }
+
+ // serialization/deserialization
+
+ /** serializes a value for transfer across the bridge. primitive types are left as is. Arrays are left as arrays, but individual
+ * values in the array are serialized according to their type. Functions and class instances are inserted into a hash table and sent
+ * across as keys into the table.
+ *
+ * For class instances, if the instance has been sent before, only its id is passed. If This is the first time the instance has been sent,
+ * a ref descriptor is sent associating the id with a type string. If this is the first time any instance of that type has been sent
+ * across, a descriptor indicating methods, properties, and variables of the type is also sent across
+ */
+ public function serialize(value:*, keep_refs:Boolean=false):*
+ {
+ var result:* = {};
+ result.newTypes = [];
+ result.newRefs = {};
+
+ if (value is Number || value is Boolean || value is String || value == null || value == undefined || value is int || value is uint)
+ {
+ result = value;
+ }
+ else if (value is Array)
+ {
+ result = [];
+ for(var i:int = 0; i < value.length; i++)
+ {
+ result[i] = serialize(value[i], keep_refs);
+ }
+ }
+ else if (value is Function)
+ {
+ // serialize a class
+ result.type = TYPE_ASFUNCTION;
+ result.value = getFunctionID(value, true);
+ }
+ else if (getQualifiedClassName(value) == "Object")
+ {
+ result.type = TYPE_ANONYMOUS;
+ result.value = value;
+ }
+ else
+ {
+ // serialize a class
+ result.type = TYPE_ASINSTANCE;
+ // make sure the type info is available
+ var className:String = getQualifiedClassName(value);
+
+ var serializer:Function = customSerializersMap[className];
+
+ // try looking up the serializer under an alternate name
+ if (serializer == null)
+ {
+ if (className.indexOf('$') > 0)
+ {
+ var split:int = className.lastIndexOf(':');
+ if (split > 0)
+ {
+ var alternate:String = className.substring(split+1);
+ serializer = customSerializersMap[alternate];
+ }
+ }
+ }
+
+ if (serializer != null)
+ {
+ return serializer.apply(null, [value, keep_refs]);
+ }
+ else
+ {
+ if (retrieveCachedTypeDescription(className, false) == null)
+ {
+ try
+ {
+ result.newTypes.push(retrieveCachedTypeDescription(className, true));
+ }
+ catch(err:Error)
+ {
+ var interfaceInfo:XMLList = describeType(value).implementsInterface;
+ for each (var interf:XML in interfaceInfo)
+ {
+ className = interf.@type.toString();
+ if (retrieveCachedTypeDescription(className, false) == null){
+ result.newTypes.push(retrieveCachedTypeDescription(className, true));
+ } //end if push new data type
+
+ } //end for going through interfaces
+ var baseClass:String = describeType(value).@base.toString();
+ if (retrieveCachedTypeDescription(baseClass, false) == null){
+ result.newTypes.push(retrieveCachedTypeDescription(baseClass, true));
+ } //end if push new data type
+ }
+ }
+
+ // make sure the reference is known
+ var objRef:Number = getRef(value, false);
+ var should_keep_ref:Boolean = false;
+ if (isNaN(objRef))
+ {
+ //create the reference if necessary
+ objRef = getRef(value, true);
+ should_keep_ref = true;
+ }
+
+ result.newRefs[objRef] = className;
+ //trace("serializing new reference: " + className + " with value" + value);
+
+ //the result is a getProperty / invokeMethod call. How can we know how much you will need the object ?
+ if (keep_refs && should_keep_ref) {
+ incRef(objRef);
+ }
+ result.value = objRef;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * deserializes a value passed in from javascript. See serialize for details on how values are packed and
+ * unpacked for transfer across the bridge.
+ */
+ public function deserialize(valuePackage:*):*
+ {
+ var result:*;
+ if (valuePackage is Number || valuePackage is Boolean || valuePackage is String || valuePackage === null || valuePackage === undefined || valuePackage is int || valuePackage is uint)
+ {
+ result = valuePackage;
+ }
+ else if(valuePackage is Array)
+ {
+ result = [];
+ for (var i:int = 0; i < valuePackage.length; i++)
+ {
+ result[i] = deserialize(valuePackage[i]);
+ }
+ }
+ else if (valuePackage.type == FABridge.TYPE_JSFUNCTION)
+ {
+ result = getRemoteFunctionProxy(valuePackage.value, true);
+ }
+ else if (valuePackage.type == FABridge.TYPE_ASFUNCTION)
+ {
+ throw new Error("as functions can't be passed back to as yet");
+ }
+ else if (valuePackage.type == FABridge.TYPE_ASINSTANCE)
+ {
+ result = resolveRef(valuePackage.value);
+ }
+ else if (valuePackage.type == FABridge.TYPE_ANONYMOUS)
+ {
+ result = valuePackage.value;
+ }
+ return result;
+ }
+
+ public function addCustomSerialization(className:String, serializationFunction:Function):void
+ {
+ customSerializersMap[className] = serializationFunction;
+ }
+
+
+ // type management
+
+ /**
+ * retrieves a type description for the type indicated by className, building one and caching it if necessary
+ */
+ public function retrieveCachedTypeDescription(className:String, createifNecessary:Boolean):Object
+ {
+ if(localTypeMap[className] == null && createifNecessary == true)
+ {
+ localTypeMap[className] = buildTypeDescription(className);
+ }
+ return localTypeMap[className];
+ }
+
+ public function addCachedTypeDescription(className:String, desc:Object):Object
+ {
+ if (localTypeMap[className] == null)
+ {
+ localTypeMap[className] = desc;
+ }
+ return localTypeMap[className];
+ }
+
+ /**
+ * builds a type description for the type indiciated by className
+ */
+ public function buildTypeDescription(className:String):Object
+ {
+ var desc:Object = {};
+
+ className = className.replace(/::/,".");
+
+ var objClass:Class = Class(ApplicationDomain.currentDomain.getDefinition(className));
+
+ var xData:XML = describeType(objClass);
+
+ desc.name = xData.@name.toString();
+
+ var methods:Array = [];
+ var xMethods:XMLList = xData.factory.method;
+ for (var i:int = 0; i < xMethods.length(); i++)
+ {
+ methods.push(xMethods[i].@name.toString());
+ }
+ desc.methods = methods;
+
+ var accessors:Array = [];
+ var xAcc:XMLList = xData.factory.accessor;
+ for (i = 0; i < xAcc.length(); i++)
+ {
+ accessors.push(xAcc[i].@name.toString());
+ }
+ xAcc = xData.factory.variable;
+ for (i = 0; i < xAcc.length(); i++)
+ {
+ accessors.push(xAcc[i].@name.toString());
+ }
+ desc.accessors = accessors;
+
+ return desc;
+ }
+
+// instance mgmt
+
+ /**
+ * resolves an instance id passed from JS to an instance previously cached for representing in JS
+ */
+ private function resolveRef(objRef:Number):Object
+ {
+ try
+ {
+ return (objRef == -1)? baseObject : localInstanceMap[objRef];
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message);
+ }
+
+ return (objRef == -1)? baseObject : localInstanceMap[objRef];
+ }
+
+ /**
+ * returns an id associated with the object provided for passing across the bridge to JS
+ */
+ public function getRef(obj:Object, createIfNecessary:Boolean):Number
+ {
+ try
+ {
+ var ref:Number;
+
+ if (createIfNecessary)
+ {
+ var newRef:Number = nextID++;
+ localInstanceMap[newRef] = obj;
+ ref = newRef;
+ }
+ else
+ {
+ for (var key:* in localInstanceMap)
+ {
+ if (localInstanceMap[key] === obj)
+ {
+ ref = key;
+ break;
+ }
+ }
+ }
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message)
+ }
+
+ return ref;
+ }
+
+
+ // function management
+
+ /**
+ * resolves a function ID passed from JS to a local function previously cached for representation in JS
+ */
+ private function resolveFunctionID(funcID:Number):Function
+ {
+ return localFunctionMap[funcID];
+ }
+
+ /**
+ * associates a unique ID with a local function suitable for passing across the bridge to proxy in Javascript
+ */
+ public function getFunctionID(f:Function, createIfNecessary:Boolean):Number
+ {
+ var ref:Number;
+
+ if (createIfNecessary)
+ {
+ var newID:Number = nextID++;
+ localFunctionMap[newID] = f;
+ ref = newID;
+ }
+ else
+ {
+ for (var key:* in localFunctionMap)
+ {
+ if (localFunctionMap[key] === f) {
+ ref = key;
+ }
+ break;
+ }
+ }
+
+ return ref;
+ }
+
+ /**
+ * returns a proxy function that represents a function defined in javascript. This function can be called syncrhonously, and will
+ * return any values returned by the JS function
+ */
+ public function getRemoteFunctionProxy(functionID:Number, createIfNecessary:Boolean):Function
+ {
+ try
+ {
+ if (remoteFunctionCache[functionID] == null)
+ {
+ remoteFunctionCache[functionID] = function(...args):*
+ {
+ var externalArgs:Array = args.concat();
+ externalArgs.unshift(functionID);
+ var serializedArgs:* = serialize(externalArgs, true);
+
+ if(checkToThrowLater(serializedArgs[1]))
+ {
+ setTimeout(function a():* {
+ try {
+ var retVal:* = ExternalInterface.call("FABridge__invokeJSFunction", serializedArgs);
+ for(var i:int = 0; i<serializedArgs.length; i++)
+ {
+ if(typeof(serializedArgs[i]) == "object" && serializedArgs[i]!=null)
+ {
+ releaseRef(serializedArgs[i].value);
+ }
+ }
+ return retVal;
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message);
+ }
+ },1);
+ }
+ else
+ {
+ var retVal:* = ExternalInterface.call("FABridge__invokeJSFunction", serializedArgs);
+ for(var i:int = 0; i<serializedArgs.length; i++)
+ {
+ if(typeof(serializedArgs[i]) == "object" && serializedArgs[i]!=null)
+ {
+ releaseRef(serializedArgs[i].value);
+ }
+ }
+ return retVal;
+ }
+ }
+ }
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message);
+ }
+
+ return remoteFunctionCache[functionID];
+ }
+
+ /**
+ * function that checks if the object on which we are working demands that it should be called at a later time, breaking the call chain
+ * we check the actual object, as well as the bsae class and interfaces
+ */
+ private function checkToThrowLater(obj:Object):Boolean
+ {
+ obj = resolveRef(obj.value);
+ var className:String = getQualifiedClassName(obj);
+ var classInfo:XML = describeType(obj);
+
+ if (FABridge.EventsToCallLater[className] != null) {
+ return true;
+ }
+
+ //check if this class doesn't inherit from one of the entries in the table
+ var inheritanceInfo:XMLList = describeType(obj).extendsClass;
+ for each (var inherit:XML in inheritanceInfo)
+ {
+ className = inherit.@type.toString();
+ if (FABridge.EventsToCallLater[className] != null) {
+ return true;
+ }
+ } //end for going through inheritance tree
+
+ //if we're still here, check the interfaces as well
+
+ var interfaceInfo:XMLList = describeType(obj).implementsInterface;
+ for each (var interf:XML in interfaceInfo)
+ {
+ className = interf.@type.toString();
+ if (FABridge.EventsToCallLater[className] != null) {
+ return true;
+ }
+ } //end for going through inheritance tree
+
+ //if nothing was found, return false, so the function gets executed
+ return false;
+ }
+
+ // callbacks exposed to JS
+
+ /**
+ * called to fetch a named property off the instanced associated with objID
+ */
+ public function js_getPropFromAS(objID:Number, propName:String):*
+ {
+ incRef(objID);
+ try
+ {
+ var obj:Object = resolveRef(objID);
+ var ret:* = serialize(obj[propName], true);
+ releaseRef(objID);
+ return ret;
+ }
+ catch (e:ItemPendingError)
+ {
+ releaseRef(objID);
+ //ItemPendingError
+ //return serialize("an error occcured with" + obj[propName]);
+ }
+ catch(e:Error)
+ {
+ releaseRef(objID);
+ return serialize("__FLASHERROR__" + "||" + e.message);
+ }
+ }
+
+ /**
+ * called to set a named property on the instance associated with objID
+ */
+ private function js_setPropertyInAS(objID:Number, propRef:String, value:*):*
+ {
+ incRef(objID);
+ try {
+ var obj:Object = resolveRef(objID);
+ obj[propRef] = deserialize(value);
+ releaseRef(objID);
+ }
+ catch(e:Error)
+ {
+ releaseRef(objID);
+ return serialize("__FLASHERROR__" + "||" + e.message);
+ }
+ }
+
+ /**
+ * accessor for retrieveing a proxy to the root object from JS
+ */
+ private function js_getRoot():*
+ {
+ try
+ {
+ //always get the root; this is the same as the get property, only it is the root object
+ var objRef:Number = getRef(baseObject, false);
+ if (isNaN(objRef))
+ {
+ //create the reference if necessary
+ objRef = getRef(baseObject, true);
+ incRef(objRef);
+ }
+ return serialize(baseObject);
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message);
+ }
+ }
+
+ /**
+ * called to invoke a function or closure associated with funcID
+ */
+ private function js_invokeFunction(funcID:Number, args:Object):*
+ {
+ var result:*;
+ try
+ {
+ var func:Function = resolveFunctionID(funcID);
+ if(func != null)
+ result = func.apply(null, deserialize(args));
+
+ return serialize(result, true);
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__"+"||"+e.message);
+ }
+ }
+
+ /**
+ * called to invoke a named method on the object associated with objID
+ */
+ private function js_invokeMethod(objID:Number, methodName:String, args:Object):*
+ {
+ incRef(objID);
+ try
+ {
+ var obj:Object = resolveRef(objID);
+ var result:*;
+
+ //check if the method is callable right now, or later
+ var callLater:Boolean = checkToExecuteLater(obj, methodName);
+
+ if (callLater) {
+ var t:Timer = new Timer(200, 1);
+ t.addEventListener(TimerEvent.TIMER, function():void {
+ var ret_inner:* = serialize(obj[methodName].apply(null, deserialize(args)), true);
+ releaseRef(objID);
+ });
+ t.start();
+ } else {
+ var ret:* = serialize(obj[methodName].apply(null, deserialize(args)), true);
+ releaseRef(objID);
+ return ret;
+ }
+ }
+ catch (e:ItemPendingError)
+ {
+ releaseRef(objID);
+ // ignore ItemPendingError
+ }
+ catch(e:Error)
+ {
+ releaseRef(objID);
+ return serialize("__FLASHERROR__" + "||" + e.message);
+ }
+ }
+
+ /**
+ * method that performs a check on the specified object and method to see if their execution should be delayed or not
+ * it checks the object, its base class and implemented interfaces
+ */
+ private function checkToExecuteLater(obj:Object, methodName:String):Boolean
+ {
+ var methods:String;
+ var className:String = getQualifiedClassName(obj);
+ var classInfo:XML = describeType(obj);
+
+ if (FABridge.MethodsToCallLater[className] != null) {
+ methods = FABridge.MethodsToCallLater[className];
+ //must call later
+ if(methods.match(methodName))
+ {
+ return true;
+ }
+ }
+
+ //check if this class doesn't inherit from one of the entries in the table
+ var inheritanceInfo:XMLList = describeType(obj).extendsClass;
+ for each (var inherit:XML in inheritanceInfo)
+ {
+ className = inherit.@type.toString();
+ if (FABridge.MethodsToCallLater[className] != null) {
+ methods = FABridge.MethodsToCallLater[className];
+ //must call later
+ if(methods.match(methodName))
+ {
+ return true;
+ }
+ }
+ } //end for going through inheritance tree
+
+ //if we're still here, check the interfaces as well
+
+ var interfaceInfo:XMLList = describeType(obj).implementsInterface;
+ for each (var interf:XML in interfaceInfo)
+ {
+ className = interf.@type.toString();
+ if (FABridge.MethodsToCallLater[className] != null) {
+ methods = FABridge.MethodsToCallLater[className];
+ //must call later
+ if(methods.match(methodName))
+ {
+ return true;
+ }
+ }
+ } //end for going through inheritance tree
+
+ //if nothing was found, return false, so the function gets executed
+ return false;
+ }
+
+ /**
+ * callback from JS to release all AS Objects from the local cache maps
+ */
+ private function js_releaseASObjects():void
+ {
+ localTypeMap = new Dictionary();
+ localInstanceMap = new Dictionary();
+ localFunctionMap = new Dictionary();
+ }
+
+ /**
+ * callback from JS to release a specific object, identified by its ID
+ */
+ private function js_releaseNamedASObject(objId:int):Boolean
+ {
+ var retVal:Boolean = false;
+ if (localInstanceMap[objId] != null)
+ {
+ delete refMap[objId];
+ delete localInstanceMap[objId];
+ retVal = true;
+ }
+ return retVal;
+ }
+
+ /**
+ * callback for js to create a new class instance.
+ */
+
+ private function js_create(className:String):*
+ {
+ try
+ {
+ var c:Class = Class(ApplicationDomain.currentDomain.getDefinition(className));
+ var instance:Object = new c();
+ }
+ catch(e:Error)
+ {
+ return serialize("__FLASHERROR__" + "||" + e.message);
+ }
+
+ // make sure the reference is known
+ var objRef:Number = getRef(instance, true);
+ incRef(objRef);
+ return serialize(instance);
+ }
+
+}
+}
diff --git a/library/ajaxchat/chat/src/index.html b/library/ajaxchat/chat/src/index.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/library/ajaxchat/chat/src/index.html
diff --git a/library/ajaxchat/readme.md b/library/ajaxchat/readme.md
new file mode 100644
index 000000000..931d8b8df
--- /dev/null
+++ b/library/ajaxchat/readme.md
@@ -0,0 +1,77 @@
+AJAX Chat Standalone
+====================
+
+This is the standalone version of Blueimp's AJAX Chat. If you are looking for a version to integrate with your forum, select a different branch.
+
+AJAX stands for "Asynchronous JavaScript and XML".
+The AJAX Chat clients (the user browsers) use JavaScript to query the web server for updates.
+Instead of delivering a complete HTML page only updated data is sent in XML format.
+
+By using JavaScript the chat page can be updated without having to reload the whole page.
+
+Requirements
+------------
+
+
+
+| *Server-Side* | *Client-Side* |
+| ---------------------- | ---------------------------- |
+| PHP >= 5 | Enabled JavaScript |
+| MySQL >= 4 | Enabled Cookies |
+| Ruby >= 1.8 (optional) | Flash Plugin >= 9 (optional) |
+
+
+Features
+--------
+- Easy installation
+- Usable as shoutbox
+- Multiple channels
+- Private messaging
+- Private channels
+- Invitation system
+- Kick/Ban or Ignore offending Users
+- Online users list with user menu
+- Emoticons/Smilies
+- Easy way to add custom emoticons
+- BBCode support
+- Optional Flash based sound support
+- Optional visual update information (changing window title)
+- Clickable Hyperlinks
+- Splitting of long words to preserve chat layout
+- Flood control
+- Possibility to delete messages inside the chat
+- IRC style commands
+- Easy interface to add custom commands
+- Possibility to define opening hours for the chat
+- Possibility to enable/disable guest users
+- Persistent client-side settings
+- Multiple languages (auto-detection of ACCEPT_LANGUAGE browser setting)
+- Multiple styles with easy layout customization through stylesheets (CSS) and templates
+- Automatic adjustment of displayed time to local client timezone
+- Standards compliance (XHTML 1.0 strict)
+- Accepts any text input, including code and special characters
+- Multiline input field with the possibility to enter line breaks
+- Message length counter
+- Realtime monitoring and logs viewer
+- Support for unicode (UTF-8) and non-unicode content types
+- Bandwidth saving update calls (only updated data is sent)
+- Optional support to push updates over a Flash based socket connection (increased performance and responsiveness)
+- Survives connection timeouts
+- Easy integration into existing authentication systems
+- Sample phpBB3, MyBB, PunBB, SMF and vBulletin integrations available
+- Separation of layout and code
+- Well commented Source Code
+- Developed with Security as integral part - built to prevent Code injections, SQL injections, Cross-site scripting (XSS), Session stealing and other attacks
+- Tested successfully with Microsoft Internet Explorer, Mozilla Firefox, Opera and Safari - built to work with all modern browsers :)
+
+
+
+Help
+----
+Essential documentation is contained in the attached readme files
+
+For more documentation consult the github wiki: https://github.com/Frug/AJAX-Chat/wiki
+
+For support questions use google groups: https://groups.google.com/forum/#!forum/ajax-chat
+
+To report bugs use github issues: https://github.com/Frug/AJAX-Chat