Commit 844f3f3b authored by Daniel Henninger's avatar Daniel Henninger Committed by dhenninger

Moment of truth, removing original location source. Insert fear here. ;)

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8236 b35dd754-fafc-0310-a699-88a17e54d16e
parent 64d9865a
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>IM Gateway Changelog</title>
<style type="text/css">
/* global font and body settings */
body {
font-size : 100%;
background-color : #d3d6d9;
padding: 0px;
margin: 0px 0px 30px 0px;
}
body, td, th {
font-family : arial, helvetica, sans-serif;
font-size : 10pt;
}
pre, tt, code {
font-family : courier new, monospace;
font-size : 9pt;
}
#pageContainer {
display: block;
position: relative;
clear: both;
background-color: #fff;
border: 1px solid #999;
padding: 40px;
margin: 30px;
-moz-border-radius: 6px;
}
#pageHeader {
display: block;
position: relative;
height: 80px;
background-color: #e7eaee;
border: 1px solid #cccccc;
border-bottom: none;
-moz-border-radius: 5px 5px 0px 0px;
margin: 10px 0px 0px 0px;
}
#pageBody {
margin: 0px 18px 0px 20px;
}
/* anchors */
a:link {
color: #11568c;
}
a:visited {
color: #571c8d;
}
a:hover {
color: #7a1d42;
text-decoration : underline;
}
a:active {
color: #7a1d42;
}
/* page header elements (logo and navigation) */
.navigation {
display: block;
position: relative;
height: 20px;
background-color: #335588;
border: 1px solid #cccccc;
border-top: none;
color: #ffffff;
font-size: 11px;
line-height: 18px;
padding: 0px 0px 0px 0px;
margin: 0px 0px 25px 0px;
overflow: hidden;
}
.navigation a {
margin: 0px 20px 0px 20px;
}
.navigation a:link { color: #ffffff; }
.navigation a:visited { color: #ffffff; }
.navigation a:hover { color: #ffffff; }
.navigation a:active { color: #ffffff; }
/* headings */
h1 {
display: block;
position: relative;
font-size : 1.7em;
font-weight : bold;
color: #670e15;
padding: 0px;
margin: 30px 0px 0px 20px;
}
h2 {
font-size : 1.3em;
font-weight : bold;
margin: 40px 0px 6px 0px;
padding: 0px;
color: #335588;
}
h3 {
font-size : 1.0em;
font-weight : bold;
margin: 25px 0px 3px 0px;
padding: 0px;
color: #334466;
}
/* general elements */
p {
margin: 0px 0px 15px 0px;
}
ul {
margin: 5px 0px 15px 35px;
}
li {
padding-bottom : 4px;
}
tt {
font-family : courier new, monospace;
font-weight : bold;
color : #060;
}
hr {
display: block;
height: 1px;
background-color: #999999;
border: none;
margin: 40px 0px 20px 0px;
}
.footer {
font-size : 8pt;
color : #666;
text-align : center;
margin-top : 2em;
padding-top : 0.5em;
border-top : 1px #CCC solid;
}
</style>
</head>
<body>
<div id="pageContainer">
<div id="pageHeader">
<h1>IM Gateway Changelog</h1>
</div>
<div id="pageBody">
<h2>Major Known Issues</h2>
<ul>
<li>Many issues with Yahoo support that I haven't been able to track down (yahoo supported moved to post-1.0)</li>
<li>Some outstanding issues with ICQ as joscar doesn't fully support ICQ yet</li>
</ul>
<h2>1.0.1 -- <span style="font-weight: normal;">April 12, 2007</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-160'>GATE-160</a>] - Now automatically logged out upon unregister</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-202'>GATE-202</a>] - Migrated to openfire layout</li>
<li>Now requires Openfire 3.3.0.</li>
</ul>
<h2>1.0 -- <span style="font-weight: normal;">March 15, 2007</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-180'>GATE-180</a>] - ICQ encoding re-fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-185'>GATE-185</a>] - If MSN client connects with same account, transport now picks up the auto-disconnect</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-189'>GATE-189</a>] - Yahoo accounts of the e-mail address variety can now be registered</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-190'>GATE-190</a>] - MSN Typing notifcation now handled inactive state</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-191'>GATE-191</a>] - Unregistering and Reregistering now triggers a proper legacy service login</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-192'>GATE-192</a>] - Registering with new password now triggers a logout/login</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-157'>GATE-157</a>] - Yahoo usernames now allow a . (period)</li>
</ul>
<b>Removals</b>
<ul>
<li>Required to remove SIP/SIMPLE support due to lack of license agreement. =(</li>
</ul>
<h2>1.0 Beta 8 -- <span style="font-weight: normal;">February 26, 2007</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-122'>GATE-122</a>] - XMPP away/whatever statuses were not being reflected in OSCAR service</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-142'>GATE-142</a>] - MSN did not properly set logged out state when connection closed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-166'>GATE-166</a>] - ICQ contacts were being auto-removed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-175'>GATE-175</a>] - MSN was not letting some users log in, I could not reproduce, but a change I made likely fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-176'>GATE-176</a>] - AIM HTML entites were not translated properly</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-181'>GATE-181</a>] - Gateway "list of users or groups" permissions check fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-182'>GATE-182</a>] - Properly handling multiple resources with same priority</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-183'>GATE-183</a>] - MSN version update was causing failed logins</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-135'>GATE-135</a>] - Registration failed in web interface now actually indicates -why- it failed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-144'>GATE-144</a>] - MSN Winks and Nudges are now relayed to XMPP user via headlines</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-147'>GATE-147</a>] - Registrations page ajax-ified</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-39'>GATE-39</a>] - EXPERIMENTAL SIP/SIMPLE Support added</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-113'>GATE-113</a>] - Retrieval of ICQ offline messages now occurs upon login</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-140'>GATE-140</a>] - Typing notification support added for MSN</li>
<li>Silenced annoying Session X idle messages in debug log.</li>
</ul>
<h2>1.0 Beta 7 -- <span style="font-weight: normal;">February 6, 2007</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-106'>GATE-106</a>] - Messages from ICQ 2003 clients are now handled properly</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-154'>GATE-154</a>] - Chat state notifications are now sent with type "chat"</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-169'>GATE-169</a>] - MsSQL issues with long vs integer resolved (may need to redo/fix your database)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-170'>GATE-170</a>] - PostgresQL issue with numeric representation of time resolved (may need to redo/fix your database)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-171'>GATE-171</a>] - Fixed composing bug that upsets ichat</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-172'>GATE-172</a>] - Web interface is no longer showing up blank under 3.2.0</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-173'>GATE-173</a>] - Full JIDs are now acceptabled in gateway permissions</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-148'>GATE-148</a>] - If some users/groups are ignored during permissions setting, now reflected after save</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-156'>GATE-156</a>] - Messages sent to remote users trying to register</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-158'>GATE-158</a>] - Killing spaces in AIM screen names automatically</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-164'>GATE-164</a>] - Messages coming in from ICQ through gateway to XMPP user are now logged (via fix in openfire 3.2.0)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-168'>GATE-168</a>] - Added ability to turn on 'percent hack' for @ translation in JIDs</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-174'>GATE-174</a>] - Separated stable transports from unstable ones in web interface</li>
</ul>
<h2>1.0 Beta 6b -- <span style="font-weight: normal;">December 20, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-152'>GATE-152</a>] - Fixed ICQ login issues</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-151'>GATE-151</a>] - Reevaluated database scripts and repaired</li>
</ul>
<h2>1.0 Beta 6a -- <span style="font-weight: normal;">December 18, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>Restored OSCAR work that IntelliJ undid for some reason.</li>
</ul>
<h2>1.0 Beta 6 -- <span style="font-weight: normal;">December 18, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-51'>GATE-51</a>] - Groupless contacts are respected as best I can</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-125'>GATE-125</a>] - AIM/ICQ group moves now work</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-128'>GATE-128</a>] - Upon unregistering from transport, roster items are now removed from roster</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-129'>GATE-129</a>] - Yahoo is now reporting bad username/password attempts</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-136'>GATE-136</a>] - MSN user add responds with subscribed message to xmpp client</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-7'>GATE-7</a>] - Access restriction support added</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-8'>GATE-8</a>] - Options can now be set from web interface</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-82'>GATE-82</a>] - Can now set default ICQ encoding</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-92'>GATE-92</a>] - Can now set ICQ encoding from admin interface</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-119'>GATE-119</a>] - OSCAR contact deletes now working</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-126'>GATE-126</a>] - Real contact list support added for IRC</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-132'>GATE-132</a>] - Now using JID escaping instead of @ -> % shrouding</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-134'>GATE-134</a>] - Admin interface now 'pings' regularly to keep session active</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-145'>GATE-145</a>] - Access controls now work from web interface</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-13'>GATE-13</a>] - Partial typing notification support added (full support in aim and icq, partial in yahoo and msn)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-86'>GATE-86</a>] - Port/hostname check added to admin interface (test connection)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-143'>GATE-143</a>] - Localization strings added for hard coded english strings</li>
</ul>
<h2>1.0 Beta 5a -- <span style="font-weight: normal;">November 10, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-121'>GATE-121</a>] - IQ Register no longer causes NPE when registration does not include x namespace uri.</li>
</ul>
<b>Improvements</b>
<ul>
<li>MSN minor protocol errors silenced for now.</li>
</ul>
<h2>1.0 Beta 5 -- <span style="font-weight: normal;">November 10, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-47'>GATE-47</a>] - Delete functionality fixed for all but OSCAR</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-71'>GATE-71</a>] - NullPointerException during registration fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-91'>GATE-91</a>] - Postgres/Other DBs duplicate key error fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-96'>GATE-96</a>] - Weird entries are no longer showing up in actual real roster in openfire</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-98'>GATE-98</a>] - MSN errors off and on while connecting fixed</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-99'>GATE-99</a>] - AIM/ICQ was not reflecting offline status when logged off</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-105'>GATE-105</a>] - Registration was not causing automatic login</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-109'>GATE-109</a>] - Could not change nicknames of MSN contacts</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-110'>GATE-110</a>] - Could not change group that MSN contacts are in</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-111'>GATE-111</a>] - CPU usage no longer hitting 100% on some systems</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-37'>GATE-37</a>] - Add/remove support fixed for MSN.</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-64'>GATE-64</a>] - IRC server and port now adjustable (via server properties)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-75'>GATE-75</a>] - Legacy service contacts adding user not detected and passed on</li>
</ul>
<h2>1.0 Beta 4 -- <span style="font-weight: normal;">October 20, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-54'>GATE-54</a>] - Buddies that are in "main"/default groups were possibly being deleted</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-59'>GATE-59</a>] - Yahoo transport no longer throws error when not available/invisible as initial state</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-62'>GATE-62</a>] - Fixed joscar library conflict</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-67'>GATE-67</a>] - Now catching a forced AIM/ICQ signoff/disconnect</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-79'>GATE-79</a>] - Status icon is now changing for icq/aim transport</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-81'>GATE-81</a>] - AIM/ICQ network connection sever is detected now</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-83'>GATE-83</a>] - Status change no longer killing gateway sessions</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-85'>GATE-85</a>] - Now send an error presence when probing non-existent user</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-87'>GATE-87</a>] - Multiple resources were not working correctly</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-95'>GATE-95</a>] - Current login status was getting confused</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-77'>GATE-77</a>] - Fixed misc bugs with MSN</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-58'>GATE-58</a>] - Messages sent when not logged in now say "you aren't logged in"</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-84'>GATE-84</a>] - Added list of ports you need to have open</li>
<li>Enabled "not functional" web interface so folk can ooh and aah over Ryan's work. =)</li>
<li>Upgraded joscar libraries.</li>
<li>Lots more debug logging.</li>
<li>Upgraded to latest JML libraries.</li>
<li>Small web interface improvements.</li>
</ul>
<h2>1.0 Beta 3a -- <span style="font-weight: normal;">October 2, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-76'>GATE-76</a>] - AIM appears to be leaving sessions logged in sometimes</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-78'>GATE-78</a>] - Valid username check is calling valid usernames invalid</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-80'>GATE-80</a>] - Oracle db schema is not working.</li>
</ul>
<h2>1.0 Beta 3 -- <span style="font-weight: normal;">September 28, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-48'>GATE-48</a>] - Password defaults to "something else" in edit dialogs (******)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-50'>GATE-50</a>] - MSN contacts being lumped together into one group (MSN Contacts)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-57'>GATE-57</a>] - Blank message content causes crashes</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-61'>GATE-61</a>] - Null email address in MSN contact list causes null pointer exception.</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-63'>GATE-63</a>] - MSN contacts should only be pulled from forward list (or treat others different)</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-65'>GATE-65</a>] - Yahoo statuses are not placed with the correct contact</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-66'>GATE-66</a>] - Should actually check for valid username entered before accepting it.</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-68'>GATE-68</a>] - Not rejecting registrations from external XMPP users</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-69'>GATE-69</a>] - Yahoo is not reporting failed logins</li>
</ul>
<b>Improvements</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-60'>GATE-60</a>] - Upgraded JML to latest version</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-70'>GATE-70</a>] - Update all Log exception calls to actually pass the exception for printing</li>
</ul>
<h2>1.0 Beta 2 -- <span style="font-weight: normal;">September 19, 2006</span></h2>
<b>Bug Fixes</b>
<ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-36'>GATE-36</a>] - Locale pieces from openfire don't carry into plugin admin interface</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-40'>GATE-40</a>] - Pseudo roster not updating properly</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-41'>GATE-41</a>] - SQLServer script should use BIGINT</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-43'>GATE-43</a>] - IRC filter button does not stay checked</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-45'>GATE-45</a>] - Removed registration does not clean up pseudo roster</li>
<li>[<a href='http://www.igniterealtime.org/issues/browse/GATE-46'>GATE-46</a>] - Migrating from other transport to gateway plugin can wipe buddy list</li>
</ul>
<h2>1.0 Beta 1a -- <span style="font-weight: normal;">September 18, 2006</span></h2>
<ul>
<li>Emergency bugfix for beta 1 to fix partial wipe of AIM/ICQ contact list.</li>
</ul>
<h2>1.0 Beta 1 -- <span style="font-weight: normal;">September 18, 2006</span></h2>
<ul>
<li>Initial beta release.</li>
</ul>
<div class="footer">
Copyright &copy; Jive Software, 2006
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
Name | Version
-------------------------------------------------------
axis.jar | 1.4
cindy.jar | 2.4.4 (patched [#4])
commons-discovery | 0.2
dwr.jar | 1.1.1 (patched [#3])
irclib.jar | 1.10
jaxrpc.jar | 1.1
jml.jar | svn-20070225
joscar-client.jar | svn-20070204 (patched [#2])
joscar-common.jar | svn-20070204
joscar-protocol.jar | svn-20070204 (patched [#2])
openymsg_network | svn-20070419
openymsg_support | svn-20070419
picocontainer.jar | 1.2.0
saaj.jar | 1.3
smack.jar | 3.0.1
smackx.jar | 3.0.1
xercesImpl.jar | 2.6.2
xml-apis.jar | 2.6.2
wsdl4j | 1.5.1
ymsg_network.jar | 0.61 (patched [#1])
ymsg_support.jar | 0.61 (patched [#1])
Patch Descriptions
1) jymsg patches
- original 0.60 patched to 0.61 via security patch
http://jymsg9.sourceforge.net/patch_0_61.zip
- adjusted build version to 0.61
- applied 'getNthValue2' patch, don't recall where i got it, effects custom status
- applied patch to fix statuses not being set correctly
http://sourceforge.net/tracker/download.php?group_id=76691&atid=547951&file_id=156956&aid=1362244
2) joscar patches
- applied patches from Damian Minkov for numerous ICQ fixes
http://groups.google.com/group/joscar-discuss/browse_thread/thread/e73fd2a3011cd0df
- applied minor patch to get ICQ encoding fixed again
3) dwr patches
- Derek did something to DWR itself to make it work, I don't have details
4) cindy patches
- silenced session X idle messages.
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<!-- Main plugin class -->
<class>org.jivesoftware.openfire.gateway.GatewayPlugin</class>
<!-- Plugin meta-data -->
<name>${gateway.name}</name>
<description>${gateway.description}</description>
<author>Daniel Henninger</author>
<version>1.0.1</version>
<date>04/12/2007</date>
<minServerVersion>3.3.0</minServerVersion>
<databaseKey>gateway</databaseKey>
<databaseVersion>2</databaseVersion>
<licenseType>gpl</licenseType>
<!-- Admin console meta-data -->
<adminconsole>
<tab id="tab-server">
<sidebar id="gateways" name="${gateway.gateways}" description="${gateway.gateways.desc}">
<item id="gateway-settings"
name="${gateway.settings}"
url="gateway-settings.jsp"
description="${gateway.settings.desc}"/>
<item id="gateway-registrations"
name="${gateway.registrations}"
url="gateway-registrations.jsp"
description="%{gateway.registrations.desc}"/>
</sidebar>
</tab>
</adminconsole>
</plugin>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Openfire Readme</title>
<style type="text/css">
/* global font and body settings */
body {
font-size : 100%;
background-color : #d3d6d9;
padding: 0px;
margin: 0px 0px 30px 0px;
}
body, td, th {
font-family : arial, helvetica, sans-serif;
font-size : 10pt;
}
pre, tt, code {
font-family : courier new, monospace;
font-size : 9pt;
}
#pageContainer {
display: block;
position: relative;
clear: both;
background-color: #fff;
border: 1px solid #999;
padding: 40px;
margin: 30px;
}
#pageHeader {
display: block;
position: relative;
height: 80px;
background-color: #e7eaee;
border: 1px solid #cccccc;
border-bottom: none;
margin: 10px 0px 0px 0px;
}
#pageBody {
margin: 0px 18px 0px 20px;
}
/* anchors */
a:link {
color: #11568c;
}
a:visited {
color: #571c8d;
}
a:hover {
color: #7a1d42;
text-decoration : underline;
}
a:active {
color: #7a1d42;
}
/* page header elements (logo and navigation) */
.navigation {
display: block;
position: relative;
height: 20px;
background-color: #335588;
border: 1px solid #cccccc;
border-top: none;
color: #ffffff;
font-size: 11px;
line-height: 18px;
padding: 0px 0px 0px 0px;
margin: 0px 0px 25px 0px;
overflow: hidden;
}
.navigation a {
margin: 0px 20px 0px 20px;
}
.navigation a:link { color: #ffffff; }
.navigation a:visited { color: #ffffff; }
.navigation a:hover { color: #ffffff; }
.navigation a:active { color: #ffffff; }
/* headings */
h1 {
display: block;
position: relative;
font-size : 1.7em;
font-weight : bold;
color: #670e15;
padding: 0px;
margin: 30px 0px 0px 20px;
}
h2 {
font-size : 1.3em;
font-weight : bold;
margin: 40px 0px 6px 0px;
padding: 0px;
color: #335588;
}
h3 {
font-size : 1.0em;
font-weight : bold;
margin: 25px 0px 3px 0px;
padding: 0px;
color: #334466;
}
/* general elements */
p {
margin: 0px 0px 15px 0px;
}
ul {
margin: 5px 0px 15px 35px;
}
li {
padding-bottom : 4px;
}
tt {
font-family : courier new, monospace;
font-weight : bold;
color : #060;
}
hr {
display: block;
height: 1px;
background-color: #999999;
border: none;
margin: 40px 0px 20px 0px;
}
.footer {
font-size : 8pt;
color : #666;
text-align : center;
margin-top : 2em;
padding-top : 0.5em;
border-top : 1px #CCC solid;
}
</style>
</head>
<body>
<div id="pageContainer">
<div id="pageHeader">
<h1>IM Gateway Readme</h1>
</div>
<div id="pageBody">
<h2>Overview</h2>
<p>
The IM (instant messaging) gateway plugin allows users to log in to and
communicate through other instant messaging services via their Jabber
accounts. The gateway itself provides a number of "transports" to other
protocols (AIM, ICQ, MSN, Yahoo, etc).
</p>
<h2>Terminology</h2>
<p>
To help identify the differences between the plugin as a whole and the
underlying interfaces to external protocols (AIM, ICQ, etc), we refer
to the plugin itself as the "gateway" while we refer to the protocol
handlers as "transports".
</p>
<h2>Installation</h2>
<p>
Copy the gateway.jar into the plugins directory of your Openfire
installation. The plugin will then be automatically deployed. To upgrade to a
new version, copy the new gateway.jar file over the existing file. Please
be aware that an upgrade will cause all of the users on your server who are
making use of the plugin to be disconnected from their external IM accounts.
Your users should be reconnected after the plugin reloads.
</p>
<h2>Configuration</h2>
<p>
By default, after the plugin has been deployed all of its features are disabled.
This plugin is configured via the "Gateways" sidebar item located in the Openfire
Admin Console. You can enable individual transports via the "Settings" sidebar
item, and add new registrations/view existing registrations from the "Registrations"
sidebar item.
</p>
<h2>Using the plugin</h2>
<p>
Before going into specifics, there are some important things you need to
know first. A user must be registered with a transport in order to make
use of it. Registration is the process wherein a user tells a transport
what username and password will be used with the external service. This
process also places the transport JID in their roster to that the
transport itself can "hear" them come online, and act appropriately (logging
them in and such). In this case, we interact with the user's roster directly,
so there is no need for a flood of subscription requests to the client itself.
A side effect of this is that only users of the local Openfire server will
be able to make use of any transport on the gateway. Roster items are created
as non-persistent, which means that when the end user logs out or disconnects
from the gateway, the associated transport roster items will no longer exist
in their roster.
</p>
<h3>For admins:</h3>
<p>
The web interface of the gateway plugin provides a mechanism for setting
up registrations on a user's behalf, as well as editing and deleting them.
It also provides tools for monitoring who is using the gateway, their status,
etc. In a typical setup, a user will be allowed to register an account
themselves. See the next section for details on this. You can also
set who has access to the specific transports and even enforce manual
registrations only. If a specific transport has any options, they will
be made available from the web interface.
</p>
<p>
If you have a firewall set up, you do not need to open any inbound ports.
However, you will need to make sure the following outgoing connections
will work based on the transport in question:
<ul>
<li>AIM: login.oscar.aol.com 5190</li>
<li>ICQ: login.oscar.aol.com 5190</li>
<li>IRC: irc.freenode.net 7000</li>
<li>MSN: messenger.hotmail.com 1863</li>
<li>Yahoo: scs.msg.yahoo.com 5050</li>
</ul>
Please be aware that these are only the initial connections made. Many of
the services will connect to other servers for difference aspects of your
legacy IM session. All of these connections should stay on the same port
though. There may be ranges of IP addresses or something that you can
open up but I do not know those lists. Also, it is now possible to change
the initial connect host and port via
<a href="http://wiki.igniterealtime.org/display/WILDFIRE/Wildfire+Properties">Openfire Properties</a>.
</p>
<p>
There is additional documentation available at:
<a href="http://wiki.igniterealtime.org/display/WILDFIRE/IM+Gateway+Plugin">IM Gateway Plugin Wiki</a>
</p>
<h3>For end users:</h3>
<p>
Typically, users will use Service Discovery (aka disco) to find out what
services are available on a server, and then will be provided with a way
to register with whatever transports are made available. Some clients
do not have the functionality to interact with transports. In this case,
a server admin will need to register the user on their behalf. (see above)
</p>
<p>
When registering with any IM Gateway transports, you will see the transport
itself show up in your XMPP roster. This is normal and is how the transport
knows when you are logged in or not, and detects status changes. Removal of
the transport roster items will typically remove your registration with the
transport as well.
</p>
<p>
<b>Special note for Spark:</b> As of this release, and an upcoming release
of Spark, you will not have the transports in your roster when you register
from Spark. This is an experimental feature for a smoother user experience.
Note that if you register from Spark and then move to another client, you
will not automatically log into any transports. If you plan to dance between
clients and not use Spark exclusively, I would recommend you register from
another client than Spark.
</p>
<h2>Trouble shooting</h2>
<p>
If the plugin behaviour is not as expected you can enable server debug logging.
This will allow the plugin to start logging. Server debug logging should only
be enabled temporarily, as it will generate a lot of additional logging that
will both slow your server down and consume a lot of disk space.
</p>
<div class="footer">
Copyright &copy; Jive Software, 2006-2007
</div>
</div>
</div>
</body>
</html>
CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL,
jid VARCHAR(255) NOT NULL,
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255),
nickname VARCHAR(255),
registrationDate BIGINT NOT NULL,
lastLogin BIGINT,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL,
jid VARCHAR(255) NOT NULL,
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255),
nickname VARCHAR(255),
registrationDate BIGINT NOT NULL,
lastLogin BIGINT,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL,
jid VARCHAR(255) NOT NULL,
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255),
nickname VARCHAR(255),
registrationDate BIGINT NOT NULL,
lastLogin BIGINT,
PRIMARY KEY (registrationID),
INDEX gatewayReg_jid_idx(jid),
INDEX gatewayReg_type_idx(transportType)
);
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255),
INDEX gatewayPsRs_regid_idx(registrationID),
INDEX gatewayPsRs_uname_idx(username)
);
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50),
INDEX gatewayRstr_ttype_idx(transportType),
INDEX gatewayRstr_uname_idx(username)
);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
CREATE TABLE gatewayRegistration (
registrationID INTEGER NOT NULL,
jid VARCHAR2(255) NOT NULL,
transportType VARCHAR2(15) NOT NULL,
username VARCHAR2(255) NOT NULL,
password VARCHAR2(255),
nickname VARCHAR2(255),
registrationDate INTEGER NOT NULL,
lastLogin INTEGER,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID INTEGER NOT NULL,
username VARCHAR2(255) NOT NULL,
nickname VARCHAR2(255),
groups VARCHAR2(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType VARCHAR2(15) NOT NULL,
username VARCHAR2(255),
groupname VARCHAR2(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
commit;
CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL,
jid VARCHAR(255) NOT NULL,
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255),
nickname VARCHAR(255),
registrationDate BIGINT NOT NULL,
lastLogin BIGINT,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
CREATE TABLE gatewayRegistration (
registrationID BIGINT NOT NULL,
jid NVARCHAR(255) NOT NULL,
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255) NOT NULL,
password NVARCHAR(255),
nickname NVARCHAR(255),
registrationDate BIGINT NOT NULL,
lastLogin BIGINT,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username NVARCHAR(255) NOT NULL,
nickname NVARCHAR(255),
groups NVARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255),
groupname NVARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
CREATE TABLE gatewayRegistration (
registrationID INTEGER NOT NULL,
jid NVARCHAR(255) NOT NULL,
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255) NOT NULL,
password NVARCHAR(255),
nickname NVARCHAR(255),
registrationDate INTEGER NOT NULL,
lastLogin INTEGER,
CONSTRAINT gatewayReg_pk PRIMARY KEY (registrationID)
);
CREATE INDEX gatewayReg_jid_idx ON gatewayRegistration (jid);
CREATE INDEX gatewayReg_type_idx ON gatewayRegistration (transportType);
CREATE TABLE gatewayPseudoRoster (
registrationID INTEGER NOT NULL,
username NVARCHAR(255) NOT NULL,
nickname NVARCHAR(255),
groups NVARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
CREATE TABLE gatewayRestrictions (
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255),
groupname NVARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
INSERT INTO jiveVersion (name, version) VALUES ('gateway', 2);
-- Add nickname to registration table
ALTER TABLE gatewayRegistration ADD COLUMN nickname VARCHAR(255);
-- Add pseudo roster table
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
-- Update database version
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
// Add nickname to registration table
ALTER TABLE gatewayRegistration ADD COLUMN nickname VARCHAR(255) BEFORE registrationDate;
// Add pseudo roster table
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
// Update database version
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
# Add nickname to registration table
ALTER TABLE gatewayRegistration ADD COLUMN nickname VARCHAR(255) NULL AFTER password;
# Add pseudo roster table
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255),
INDEX gatewayPsRs_regid_idx(registrationID),
INDEX gatewayPsRs_uname_idx(username)
);
# Update database version
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
-- Add nickname column to registration table
ALTER TABLE gatewayRegistration ADD nickname VARCHAR2(255) NULL;
-- Add pseudo roster table
CREATE TABLE gatewayPseudoRoster (
registrationID INTEGER NOT NULL,
username VARCHAR2(255) NOT NULL,
nickname VARCHAR2(255),
groups VARCHAR2(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
-- Update database version
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
commit;
-- Add nickname column to registration table
ALTER TABLE gatewayRegistration ADD COLUMN nickname VARCHAR(255);
-- Add pseudo roster table
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username VARCHAR(255) NOT NULL,
nickname VARCHAR(255),
groups VARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
-- Update database version
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
/* Add nickname column to registration table */
ALTER TABLE gatewayRegistration ADD nickname NVARCHAR(255);
/* Add pseudo roster table */
CREATE TABLE gatewayPseudoRoster (
registrationID BIGINT NOT NULL,
username NVARCHAR(255) NOT NULL,
nickname NVARCHAR(255),
groups NVARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
/* Update database version */
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
/* Add nickname column to registration table */
ALTER TABLE gatewayRegistration ADD nickname NVARCHAR(255);
/* Add pseudo roster table */
CREATE TABLE gatewayPseudoRoster (
registrationID INTEGER NOT NULL,
username NVARCHAR(255) NOT NULL,
nickname NVARCHAR(255),
groups NVARCHAR(255)
);
CREATE INDEX gatewayPsRs_regid_idx ON gatewayPseudoRoster (registrationID);
CREATE INDEX gatewayPsRs_uname_idx ON gatewayPseudoRoster (username);
/* Update database version */
UPDATE jiveVersion SET version = 1 WHERE name = 'gateway';
-- Add restrictions table
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
-- Update database version
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
// Add restrictions table
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
// Update database version
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
# Add restrictions table
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50),
INDEX gatewayRstr_ttype_idx(transportType),
INDEX gatewayRstr_uname_idx(username)
);
# Update database version
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
-- Add restrictions table
CREATE TABLE gatewayRestrictions (
transportType VARCHAR2(15) NOT NULL,
username VARCHAR2(255),
groupname VARCHAR2(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
-- Update database version
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
commit;
-- Add restrictions table
CREATE TABLE gatewayRestrictions (
transportType VARCHAR(15) NOT NULL,
username VARCHAR(255),
groupname VARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
-- Update database version
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
/* Add restrictions table */
CREATE TABLE gatewayRestrictions (
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255),
groupname NVARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
/* Update database version */
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
/* Add restrictions table */
CREATE TABLE gatewayRestrictions (
transportType NVARCHAR(15) NOT NULL,
username NVARCHAR(255),
groupname NVARCHAR(50)
);
CREATE INDEX gatewayRstr_ttype_idx ON gatewayRestrictions (transportType);
CREATE INDEX gatewayRstr_uname_idx ON gatewayRestrictions (username);
/* Update database version */
UPDATE jiveVersion SET version = 2 WHERE name = 'gateway';
##
## IM Gateway Resource Bundle
##
## Additional locales can be specified by creating a new resource file in this
## directory using the following conventions:
##
## gateway_i18n "_" language "_" country ".properties"
## gateway_i18n "_" language ".properties"
##
## e.g.
## gateway_i18n.properties <- English resources (default)
## gateway_i18n_en_US.properties <- American US resources
## gateway_i18n_de.properties <- German resources
## gateway_i18n_ja.properties <- Japanese resources
##
## Please note that the two digit language code should be lower case, and the
## two digit country code should be in uppercase. Often, it is not necessary to
## specify the country code.
##
## A full list of language codes can be found at
## http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt
## and a full list of country codes can be found at
## http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
##
## In property strings that are parameterized, single quotes can be used to
## quote the "{" (curly brace) if necessary. A real single quote is represented by ''.
##
## REVISION HISTORY (by IM Gateway version):
##
## 1.0 Beta 1
## Added key: 'gateway.aim.name'
## Added key: 'gateway.aim.username'
## Added key: 'gateway.aim.password'
## Added key: 'gateway.aim.registration'
## Added key: 'gateway.icq.name'
## Added key: 'gateway.icq.username'
## Added key: 'gateway.icq.password'
## Added key: 'gateway.icq.registration'
## Added key: 'gateway.msn.name'
## Added key: 'gateway.msn.username'
## Added key: 'gateway.msn.password'
## Added key: 'gateway.msn.registration'
## Added key: 'gateway.yahoo.name'
## Added key: 'gateway.yahoo.username'
## Added key: 'gateway.yahoo.password'
## Added key: 'gateway.yahoo.registration'
## Added key: 'gateway.irc.name'
## Added key: 'gateway.irc.username'
## Added key: 'gateway.irc.password'
## Added key: 'gateway.irc.nickname'
## Added key: 'gateway.irc.registration'
##
## 1.0 Beta 2
## Added key: 'login.title'
## Added key: 'global.add'
## Added key: 'global.edit'
## Added key: 'global.cancel'
## Added key: 'global.save_changes'
## Added key: 'gateway.aim.shortservice'
## Added key: 'gateway'aim.service'
## Added key: 'gateway.icq.shortservice'
## Added key: 'gateway'icq.service'
## Added key: 'gateway.irc.shortservice'
## Added key: 'gateway'irc.service'
## Added key: 'gateway.msn.shortservice'
## Added key: 'gateway'msn.service'
## Added key: 'gateway.yahoo.shortservice'
## Added key: 'gateway'yahoo.service'
## Added key: 'gateway.web.settings.instructions'
## Added key: 'gateway.web.registrations.instructions'
## Added key: 'gateway.web.registrations.addnewreg'
## Added key: 'gateway.web.registrations.cancelnewreg'
## Added key: 'gateway.web.registrations.username'
## Added key: 'gateway.web.registrations.password'
## Added key: 'gateway.web.registrations.nickname'
## Added key: 'gateway.web.registrations.jid'
## Added key: 'gateway.web.registrations.gateway'
## Added key: 'gateway.web.registrations.signedon'
## Added key: 'gateway.web.registrations.update'
## Added key: 'gateway.web.registrations.regsuccess'
## Added key: 'gateway.web.registrations.regfailure'
## Added key: 'gateway.web.registrations.next'
## Added key: 'gateway.web.registrations.prev'
## Added key: 'gateway.web.registrations.remove'
## Added key: 'gateway.web.registrations.edit'
## Added key: 'gateway.web.registrations.lastlogin'
## Added key: 'gateway.web.registrations.serviceusername'
## Added key: 'gateway.web.registrations.user'
## Added key: 'gateway.web.registrations.confirmdelete'
## Added key: 'gateway.web.registrations.registrations'
##
## 1.0 Beta 6
## Added key: 'gateway.web.settings.tests'
## Added key: 'gateway.web.settings.options'
## Added key: 'gateway.web.settings.permissions'
## Added key: 'gateway.web.settings.connecttohost'
## Added key: 'gateway.web.settings.connecttoport'
## Added key: 'gateway.web.settings.testconnection'
## Added key: 'gateway.web.settings.saveoptions'
## Added key: 'gateway.web.settings.cancelchanges'
## Added key: 'gateway.web.settings.registernone'
## Added key: 'gateway.web.settings.registersome'
## Added key: 'gateway.web.settings.registerall'
## Added key: 'gateway.web.settings.users'
## Added key: 'gateway.web.settings.groups'
## Added key: 'gateway.web.settings.savepermissions'
## Added key: 'gateway.web.settings.title'
## Added key: 'gateway.web.settings.settingssaved'
## Added key: 'gateway.web.settings.success'
## Added key: 'gateway.web.settings.failed'
## Added key: 'gateway.web.settings.permissionssaved'
## Added key: 'gateway.web.registrations.title'
## Added key: 'gateway.web.settings.host'
## Added key: 'gateway.web.settings.port'
## Added key: 'gateway.web.settings.encoding'
## Added key: 'gateway.oscar.connectionfailed'
## Added key: 'gateway.oscar.accountdeleted'
## Added key: 'gateway.oscar.badinput'
## Added key: 'gateway.oscar.badpassword'
## Added key: 'gateway.oscar.oldclient'
## Added key: 'gateway.oscar.connectedtoomuch'
## Added key: 'gateway.oscar.baduserorpass'
## Added key: 'gateway.oscar.accountsuspended'
## Added key: 'gateway.oscar.unknownerror'
## Added key: 'gateway.oscar.disconnected'
## Added key: 'gateway.oscar.away'
## Added key: 'gateway.aim.warninganon'
## Added key: 'gateway.aim.warningdirect'
## Added key: 'gateway.msn.passwordincorrect'
## Added key: 'gateway.msn.sendmsgfailed'
## Added key: 'gateway.msn.illegalaccount'
## Added key: 'gateway.yahoo.error'
## Added key: 'gateway.yahoo.mail'
## Added key: 'gateway.yahoo.loginrefused'
## Added key: 'gateway.yahoo.unknownuser'
## Added key: 'gateway.yahoo.badpassword'
## Added key: 'gateway.yahoo.accountlocked'
## Added key: 'gateway.yahoo.accountlockedwithurl'
## Added key: 'gateway.yahoo.unknownerror'
## Added key: 'gateway.irc.away'
## Added key: 'gateway.irc.extendedaway'
## Added key: 'gateway.irc.donotdisturb'
## Added key: 'gateway.irc.errorreceived'
## Added key: 'gateway.irc.errorreceivedwithcode'
## Added key: 'gateway.base.notloggedin'
## Added key: 'gateway.base.enterusername'
## Added key: 'gateway.web.settings.cancelledchanges'
##
## 1.0 Beta 7
## Added key: 'gateway.base.registrationdeniedbyacls'
## Added key: 'gateway.base.registrationdeniedbyhost'
## Added key: 'gateway.base.registrationdeniednoacct'
## Added key: 'gateway.base.registrationdeniedbadusername'
## Added key: 'gateway.web.settings.unstable.title'
## Added key: 'gateway.web.settings.unstable.notice'
##
## 1.0 Beta 8
## Added key: 'gateway.sip.shortservice'
## Added key: 'gateway.sip.service'
## Added key: 'gateway.sip.name'
## Added key: 'gateway.sip.username'
## Added key: 'gateway.sip.password'
## Added key: 'gateway.sip.registration'
## Added key: 'gateway.sip.passwordincorrect'
## Added key: 'gateway.sip.sendmsgfailed'
## Added key: 'gateway.sip.illegalaccount'
## Updated key: 'gateway.web.settings.unstable.title'
## Updated key: 'gateway.web.settings.unstable.notice'
## Added key: 'gateway.web.registrations.xmppnotfound'
## Added key: 'gateway.web.registrations.regnotfound'
## Added key: 'gateway.web.registrations.notenabled'
## Added key: 'gateway.web.registrations.illegaldomain'
## Added key: 'gateway.web.registrations.invaliduser'
## Added key: 'gateway.msn.illegalaccount'
## Added key: 'gateway.msn.disconnect'
## Added key: 'gateway.msn.wink'
## Added key: 'gateway.msn.nudge'
## Added key: 'gateway.web.registrations.deletesuccess'
## Added key: 'gateway.web.registrations.updatesuccess'
## Added key: 'gateway.web.registrations.addsuccess'
## Removed key: 'gateway.web.registrations.regsuccess'
## Removed key: 'gateway.web.registrations.regfailure'
## Added key: 'global.delete'
##
## 1.0
## Added key: 'gateway.msn.otherloggedin'
## Removed key: 'gateway.sip.shortservice'
## Removed key: 'gateway.sip.service'
## Removed key: 'gateway.sip.name'
## Removed key: 'gateway.sip.username'
## Removed key: 'gateway.sip.password'
## Removed key: 'gateway.sip.registration'
## Removed key: 'gateway.sip.passwordincorrect'
## Removed key: 'gateway.sip.sendmsgfailed'
## Removed key: 'gateway.sip.illegalaccount'
##
## 1.0.1
## Added key: 'gateway.name'
## Added ley: 'gateway.description'
## Added key: 'gateway.gateways'
## Added key: 'gateway.gateways.desc'
## Added key: 'gateway.settings'
## Added key: 'gateway.settings.desc'
## Added key: 'gateway.registrations'
## Added key: 'gateway.registrations.desc'
##
## 1.1.0
## Added key: 'gateway.web.registrations.never'
## Added key: 'gateway.web.registrations.page'
## Added key: 'gateway.web.registrations.perpage'
# Temporary Tags Until Fixed Properly
login.title=Admin Console
global.add=Add
global.edit=Edit
global.delete=Delete
global.cancel=Cancel
global.save_changes=Save Changes
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=You are not currently logged into the {0} transport.
gateway.base.enterusername=Please enter the {0} username of the person you want to add.
gateway.base.registrationdeniedbyacls=Your registration was denied due to your account not being in the access list.
gateway.base.registrationdeniedbyhost=Your registration was denied due to your account not existing on the same server as the transport.
gateway.base.registrationdeniednoacct=Your registration was denied due to you not having a registered account on the server.
gateway.base.registrationdeniedbadusername=Your registration was denied because the username you provided was not valid for the service.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=Connection failed:
gateway.oscar.accountdeleted=This account has been deleted.
gateway.oscar.badinput=Illegal screen name/uin specified.
gateway.oscar.badpassword=Incorrect password specified.
gateway.oscar.oldclient=Plugin is identifying itself as too old of a client. Please contact the developer.
gateway.oscar.connectedtoomuch=You have connected too many times in too short of a time frame. Please wait around 15 minutes before trying again.
gateway.oscar.baduserorpass=Invalid screen name or password specified. Please re-register with a valid screen name and password.
gateway.oscar.accountsuspended=Your account has been temporarily suspended.
gateway.oscar.unknownerror=Unknown error code returned from AIM: {0}\nURL: {1}
gateway.oscar.disconnected=You have been disconnected automatically by the server.
gateway.oscar.away=Away
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=AIM Transport
gateway.aim.username=ScreenName
gateway.aim.password=Password
gateway.aim.registration=Please enter your AIM ScreenName and password.
gateway.aim.warninganon=You have received an anonymous AIM warning. Your warning level is now {0}%.
gateway.aim.warningdirect=You have received an AIM warning from {0}. Your warning level is now {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=ICQ Transport
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Password
gateway.icq.registration=Please enter your ICQ# (UIN) and password.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=MSN Transport
gateway.msn.username=E-Mail Address
gateway.msn.password=Password
gateway.msn.registration=Please enter your MSN Passport e-mail address and password.
gateway.msn.passwordincorrect=The password you registered with is incorrect. Please re-register with the correct password.
gateway.msn.sendmsgfailed=Unable to send MSN message. Reason:
gateway.msn.illegalaccount=You are registered with the MSN transport with an illegal account name.\nThe account name should look like an email address.\nYou registered as:
gateway.msn.disconnect=You were disconnected from the MSN service.
gateway.msn.wink=You have received an MSN wink.
gateway.msn.nudge=You have received an MSN nudge.
gateway.msn.otherloggedin=You were disconnected from MSN because your account signed in at another location.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Yahoo! Transport
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=Password
gateway.yahoo.registration=Please enter your Yahoo! ID and password.
gateway.yahoo.error=Error from Yahoo:
gateway.yahoo.mail=You have {0} message(s) waiting in your Yahoo! mail.
gateway.yahoo.loginrefused=Failed to log into Yahoo! messenger account. (login refused)
gateway.yahoo.unknownuser=Yahoo! did not recognize the username you registered with. Please re-register with correct username.
gateway.yahoo.badpassword=Login refused by Yahoo!, perhaps because of a bad password. Please re-register with correct password.
gateway.yahoo.accountlocked=Access to your Yahoo! account is locked.
gateway.yahoo.accountlockedwithurl=Access to your Yahoo! account is locked. Please visit {0}
gateway.yahoo.unknownerror=Failed to log into Yahoo! messenger account. (unknown error)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=IRC Transport
gateway.irc.username=Username
gateway.irc.password=Password
gateway.irc.nickname=Nickname
gateway.irc.registration=Please enter your IRC username, password, and nickname. Nickname is the primary username used while username and password are used for authentication. If no password is required, leave it blank.
gateway.irc.away=Away
gateway.irc.extendedaway=Extended Away
gateway.irc.donotdisturb=Do Not Disturb
gateway.irc.errorreceived=IRC error received:
gateway.irc.errorreceivedwithcode=IRC error received (code {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=Select which gateways will be allowed, what features are available, and who can connect to each gateway service. Checking a gateway enables the service.
gateway.web.settings.tests=Tests
gateway.web.settings.options=Options
gateway.web.settings.permissions=Permissions
gateway.web.settings.connecttohost=Connect to host
gateway.web.settings.connecttoport=Connect to port
gateway.web.settings.testconnection=Test Connection
gateway.web.settings.saveoptions=Save Options
gateway.web.settings.cancelchanges=Cancel Changes
gateway.web.settings.registernone=Manual registration only (see the Registrations section to manage)
gateway.web.settings.registersome=These users and/or groups can register
gateway.web.settings.registerall=All users can register
gateway.web.settings.users=Users
gateway.web.settings.groups=Groups
gateway.web.settings.savepermissions=Save Permissions
gateway.web.settings.title=Gateway Settings
gateway.web.settings.settingssaved=Settings Saved
gateway.web.settings.cancelledchanges=Cancelled Changes
gateway.web.settings.success=Success
gateway.web.settings.failed=Failed
gateway.web.settings.permissionssaved=Permissions Saved
gateway.web.settings.host=Host
gateway.web.settings.port=Port
gateway.web.settings.encoding=Encoding
gateway.web.settings.unstable.title=Experimental Gateways
gateway.web.settings.unstable.notice=The following gateways are experimental and are not recommended in a production environment. They are provided for those interested in trying out unstable services and are comfortable knowing they may not work correctly.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Below is a list of all gateway service registrations. To filter by active sessions and/or specific gateways select the options below and update the view.
gateway.web.registrations.addnewreg=Add a new registration
gateway.web.registrations.cancelnewreg=Cancel adding new registration
gateway.web.registrations.username=username
gateway.web.registrations.password=password
gateway.web.registrations.nickname=nickname
gateway.web.registrations.jid=user (JID)
gateway.web.registrations.gateway=gateway
gateway.web.registrations.signedon=Signed on only
gateway.web.registrations.update=Update
gateway.web.registrations.next=Next
gateway.web.registrations.prev=Prev
gateway.web.registrations.remove=Remove
gateway.web.registrations.edit=Edit
gateway.web.registrations.lastlogin=Last Login
gateway.web.registrations.serviceusername=Service/Username
gateway.web.registrations.user=User
gateway.web.registrations.confirmdelete=Are you sure you want to delete this registration?
gateway.web.registrations.registrations=Registrations
gateway.web.registrations.title=Gateway Registrations
gateway.web.registrations.xmppnotfound=Unable to find XMPP user account.
gateway.web.registrations.regnotfound=Unable to find registration.
gateway.web.registrations.notenabled=Transport is not enabled. Please enable before attempting operation.
gateway.web.registrations.illegaldomain=XMPP user account domain is not on this server.
gateway.web.registrations.invaliduser=Invalid username specified for legacy service.
gateway.web.registrations.deletesuccess=Registration successfully deleted.
gateway.web.registrations.updatesuccess=Registration successfully updated.
gateway.web.registrations.addsuccess=Registration successfully added.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
##
## IM Gateway Resource Bundle - German locale (de)
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=Adminkonsole
global.add=Hinzuf\u00fcgen
global.edit=Bearbeiten
global.cancel=Abbrechen
global.save_changes=\u00c4nderungen speichern
global.delete=L\u00f6schen
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=Sie sind momentan nicht am {0} Transport angemeldet.
gateway.base.enterusername=Bitte geben Sie den {0} Benutzernamen derjenigen Person an, die sie hinzuf\u00fcgen wollen.
gateway.base.registrationdeniedbyacls=Ihre Registrierung wurde verweigert, weil ihr Konto nicht in der Zugriffsliste ist.
gateway.base.registrationdeniedbyhost=Ihre Registrierung wurde verweigert, weil ihr Konto nicht auf dem gleichen Server existiert wie der Transport.
gateway.base.registrationdeniednoacct=Ihre Registrierung wurde verweigert, weil sie kein Konto auf diesem Server haben.
gateway.base.registrationdeniedbadusername=Ihre Registrierung wurde verweigert, weil der von ihnen angegebene Benutzername f\u00fcr diesen Service ung\u00fcltig ist.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=Verbindung fehlgeschlagen:
gateway.oscar.accountdeleted=Dieser Account wurde gel\u00f6scht.
gateway.oscar.badinput=Ung\u00fcltiger Benutzername/UIN angegeben.
gateway.oscar.badpassword=Ung\u00fcltiges Passwort angegeben.
gateway.oscar.oldclient=Dieses Plugin identifiziert sich als zu alter Client. Bitte benachrichtigen Sie den Entwickler.
gateway.oscar.connectedtoomuch=Sie haben sich zu oft in zu kurzer Zeit verbunden. Bitte warten Sie ungef\u00e4hr 15 Minuten vor einem erneuten Versuch.
gateway.oscar.baduserorpass=Ung\u00fcltiger Benutzername oder Passwort. Bitte registrieren Sie sich erneut mit einem g\u00fcltigen Namen und Passwort.
gateway.oscar.accountsuspended=Ihr Account wurde tempor\u00e4r gesperrt.
gateway.oscar.unknownerror=AIM gab einen unbekannten Fehler zur\u00fcck: {0}\nURL: {1}
gateway.oscar.disconnected=Sie wurden automatisch vom Server getrennt.
gateway.oscar.away=Abwesend
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=AIM Transport
gateway.aim.username=Benutzername
gateway.aim.password=Passwort
gateway.aim.registration=Bitte geben Sie ihren AIM Benutzernamen und das Passwort ein.
gateway.aim.warninganon=Sie haben eine anonyme AIM Verwarnung erhalten. Ihr Warnungslevel ist nun {0}%.
gateway.aim.warningdirect=Sie haben eine AIM Verwarnung von {0} erhalten. Ihr Warnungslevel ist nun {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=ICQ Transport
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Passwort
gateway.icq.registration=Bitte geben Sie Ihre ICQ Nummer (UIN) und das Passwort ein.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=MSN Transport
gateway.msn.username=E-Mailadresse
gateway.msn.password=Passwort
gateway.msn.registration=Bitte geben Sie Ihre E-Mailadresse und Passwort f\u00fcr das MSN Passport ein.
gateway.msn.passwordincorrect=Das Passwort mit dem Sie sich registriert haben ist falsch. Bitte registrieren Sie sich erneut mit dem korrekten Passwort.
gateway.msn.sendmsgfailed=Versenden einer MSN Nachricht fehlgeschlagen. Grund:
gateway.msn.illegalaccount=Sie sind bei dem MSN Transport mit einem illegalen Accountnamen registriert.\nDer Accountname muss wie eine E-Mailadresse aussehen.\nSie haben sich mit folgendem Namen registriert:
gateway.msn.disconnect=Du wurdest von MSN getrennt.
gateway.msn.wink=Du wurdest von einem MSN-Nutzer angezwinkert.
gateway.msn.nudge=Ein MSN-Nutzer will Deine Aufmerksamkeit.
gateway.msn.otherloggedin=Du wurdest von MSN ausgeloggt, weil Du mit einem anderen Client online gegangen bist.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Yahoo! Transport
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=Passwort
gateway.yahoo.registration=Bitte geben Sie Ihre Yahoo! ID und das Passwort ein.
gateway.yahoo.error=Fehler von Yahoo:
gateway.yahoo.mail=Sie haben {0} Nachricht(en) in Ihrem Yahoo! E-Mailaccount.
gateway.yahoo.loginrefused=Die Anmeldung Ihres Yahoo! Messenger Accounts schlug fehl. (Login verweigert)
gateway.yahoo.unknownuser=Yahoo! hat den Benutzernamen mit denen Sie sich angemeldet haben nicht erkannt. Bitte registrieren Sie sich erneut mit dem korrekten Namen.
gateway.yahoo.badpassword=Die Anmeldung wurde von Yahoo! verweigert, m\u00f6glicherweise aufgrund eines falschen Passwortes. Bitte registrieren Sie sich erneut mit dem korrekten Passwort.
gateway.yahoo.accountlocked=Der Zugang zu Ihrem Yahoo! Account ist gesperrt.
gateway.yahoo.accountlockedwithurl=Der Zugang zu Ihrem Yahoo! account ist gesperrt. Bitte besuchen sie {0}
gateway.yahoo.unknownerror=Die Anmeldung Ihres Yahoo! Messenger Accounts schlug fehl. (Unbekannter Fehler)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=Internet Relay Chat
gateway.irc.name=IRC Transport
gateway.irc.username=Benutzername
gateway.irc.password=Passwort
gateway.irc.nickname=Nickname
gateway.irc.registration=Bitte geben Sie Ihren IRC Benutzername, das Passwort und den Nickname ein. Der Benutzername und das Passwort werden f\u00fcr die Authentifizierung benutzt. Wird kein Passwort ben\u00f6tigt, lassen Sie das Feld frei.
gateway.irc.away=Abwesend
gateway.irc.extendedaway=Nicht verf\u00fcgbar
gateway.irc.donotdisturb=Nicht st\u00f6ren
gateway.irc.errorreceived=IRC Fehler erhalten:
gateway.irc.errorreceivedwithcode=IRC Fehler erhalten (Code {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=W\u00e4hlen Sie aus, welches Gateway Sie aktivieren m\u00f6chten, welche Optionen verf\u00fcgbar sind und welche Benutzer diese nutzen d\u00fcrfen.
gateway.web.settings.tests=Tests
gateway.web.settings.options=Optionen
gateway.web.settings.permissions=Berechtigungen
gateway.web.settings.connecttohost=Verbinde zu Host
gateway.web.settings.connecttoport=Verbinde zu Port
gateway.web.settings.testconnection=Verbindungstest
gateway.web.settings.saveoptions=Optionen speichern
gateway.web.settings.cancelchanges=\u00c4nderungen verwerfen
gateway.web.settings.registernone=Nur manuelle Registrierung (siehe Registrierungsverwaltung)
gateway.web.settings.registersome=Diese Benutzer und/oder Gruppen k\u00f6nnen sich registrieren
gateway.web.settings.registerall=Alle Benutzer k\u00f6nnen sich registrieren
gateway.web.settings.users=Benutzer
gateway.web.settings.groups=Gruppen
gateway.web.settings.savepermissions=Berechtigungen speichern
gateway.web.settings.title=Gateway Einstellungen
gateway.web.settings.settingssaved=Einstellungen gespeichert
gateway.web.settings.cancelledchanges=\u00c4nderungen verworfen
gateway.web.settings.success=Erfolg
gateway.web.settings.failed=Fehlgeschlagen
gateway.web.settings.permissionssaved=Berechtigungen gespeichert
gateway.web.settings.host=Host
gateway.web.settings.port=Port
gateway.web.settings.encoding=Encoding
gateway.web.settings.unstable.title=Experimentelle Gateways
gateway.web.settings.unstable.notice=Diese Gateways sind im Teststadium und sollten nicht in wichtigen Umgebungen eingesetzt werden, und k\u00f6nnen unzuverl\u00e4ssig arbeiten.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Eine Auflistung der IM Gateway Registrierungen ist unten verf\u00fcgbar. Sie k\u00f6nnen diese nach Typ und Benutzernamen filtern.
gateway.web.registrations.addnewreg=Neue Registrierung hinzuf\u00fcgen
gateway.web.registrations.cancelnewreg=Anlegen der Registrierung abbrechen
gateway.web.registrations.username=Benutzername
gateway.web.registrations.password=Passwort
gateway.web.registrations.nickname=Nickname
gateway.web.registrations.jid=Benutzer (JID)
gateway.web.registrations.gateway=Gateway
gateway.web.registrations.signedon=Nur Angemeldet
gateway.web.registrations.update=Aktualisieren
gateway.web.registrations.next=Weiter
gateway.web.registrations.prev=Zur\u00fcck
gateway.web.registrations.remove=Entfernen
gateway.web.registrations.edit=Bearbeiten
gateway.web.registrations.lastlogin=Letzter Login
gateway.web.registrations.serviceusername=Service/Benutzername
gateway.web.registrations.user=Benutzer
gateway.web.registrations.confirmdelete=Wollen Sie diese Registrierung wirklich l\u00f6schen?
gateway.web.registrations.registrations=Registrierungen
gateway.web.registrations.title=Gateway Registrationen
gateway.web.registrations.xmppnotfound=Konnte keinen XMPP Benutzeraccount finden.
gateway.web.registrations.regnotfound=Kann keine Registrierung finden.
gateway.web.registrations.notenabled=Gateway ist nicht aktiv. Bitte vor Nutzung aktivieren.
gateway.web.registrations.illegaldomain=Die Domain des Benutzeraccounts ist nicht auf diesem Server.
gateway.web.registrations.invaliduser=Ung\u00fcltiger Benutzername f\u00fcr das Gateway.
gateway.web.registrations.deletesuccess=Registrierung erfolgreich gel\u00f6scht.
gateway.web.registrations.updatesuccess=Registrierung erfolgreich aktualisiert.
gateway.web.registrations.addsuccess=Registrierung erfolgreich hinzugef\u00fcgt.
gateway.web.registrations.never=noch nie
gateway.web.registrations.page=Seite
gateway.web.registrations.perpage=pro Seite
##
## IM Gateway Resource Bundle - Spanish locale (es)
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=Consola de Administracion
global.add=Agregar
global.edit=Editar
global.cancel=Cancelar
global.save_changes=Salvar Cambios
global.delete=Eliminar
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=En este momento no te encuentras autenticado en el transporte {0}.
gateway.base.enterusername=Por favor introduce el nombre de usuario {0} de la persona que deseas agregar.
gateway.base.registrationdeniedbyacls=Su registraci\u00f3n fue denegada ya que su cuenta no tiene permisos de acceso a este gateway.
gateway.base.registrationdeniedbyhost=Su registraci\u00f3n fue denegada ya que su cuenta no existe en el mismo servidor que el transporte.
gateway.base.registrationdeniednoacct=u registraci\u00f3n fue denegada ya que no posee una cuenta en el este servidor.
gateway.base.registrationdeniedbadusername=Su registraci\u00f3n fue denegada ya que el nombre de usuario especificado no es v\u00e1lido para este servicio.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=La conexion fallo:
gateway.oscar.accountdeleted=Esta cuenta ha sido borrada.
gateway.oscar.badinput=Nombre/uin especificado incorrectamente.
gateway.oscar.badpassword=Contrasena especificada incorrectamente.
gateway.oscar.oldclient=Plugin identificado muy obsoleto para el cliente. Por favor contacta al desarrollador.
gateway.oscar.connectedtoomuch=Te has conectado muchas ocasiones en un periodo de tiempo reducido. Por favor espera alrededor de 15 minutos antes de que intentes nuevamente.
gateway.oscar.baduserorpass=Nombre de usuario o contrasena invalidos. Por favor intenta registrarte nuevamente con un nombre o contrasena validos.
gateway.oscar.accountsuspended=Tu cuenta ha sido temporalmente suspendida.
gateway.oscar.unknownerror=Codigo de error desconocido obtenido de AIM: {0}\nURL: {1}
gateway.oscar.disconnected=Has sido desconectado automaticamente por el servidor.
gateway.oscar.away=Ausente
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=Transporte AIM
gateway.aim.username=Nombre de usuario
gateway.aim.password=Password
gateway.aim.registration=Por favor introduce tu nombre de usuario AIM y contrasena.
gateway.aim.warninganon=Has recibido una alerta AIM anonima. Tu nivel de alertamiento actual es {0}%.
gateway.aim.warningdirect=Has recibido una alerta AIM de {0}. Tu nivel de alertamiento actual es {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=Transporte ICQ
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Password
gateway.icq.registration=Por favor introduce tu ICQ# (UIN) y password.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=Transporte MSN
gateway.msn.username=Direccion de correo MSN
gateway.msn.password=Password
gateway.msn.registration=Por favor introduce tu direccion de correo de MSN Passport y password.
gateway.msn.passwordincorrect=El password que has registrado es incorrecto. Por favor repite el procedimiento de registro con un password correcto.
gateway.msn.sendmsgfailed=No se pudo enviar un mensaje MSN. Razon:
gateway.msn.illegalaccount=Estas registrado con el transporte MSN con un nombre de cuenta invalido.\nEl nombre de la cuenta debe de tener la estructura de una direccion de correo electronico.\nTe registraste como:
gateway.msn.disconnect=Has sido desconectado del servicio de MSN.
gateway.msn.wink=Has recibido un guino de MSN!.
gateway.msn.nudge=Has recibido un zumbido de MSN!.
gateway.msn.otherloggedin=Has sido desconectado de MSN porque tu cuenta ha sido autenticada en otro lugar.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Transporte Yahoo!
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=Password
gateway.yahoo.registration=Por favor introduce tu Yahoo! ID y password.
gateway.yahoo.error=Error de Yahoo:
gateway.yahoo.mail=Tienes {0} mensaje(s) en tu Yahoo! mail.
gateway.yahoo.loginrefused=No se pudo autenticar con la cuenta del mensajero de Yahoo!. (usuario denegado)
gateway.yahoo.unknownuser=Yahoo! no reconocio el username que registraste. Por favor intenta el registro nuevamente con un nombre de usuario valido.
gateway.yahoo.badpassword=Acceso denegado por Yahoo!, es probable que el password este incorrecto. Por favor intenta el registro nuevamente con un password valido.
gateway.yahoo.accountlocked=El acceso a tu cuenta de Yahoo! esta bloqueado.
gateway.yahoo.accountlockedwithurl=El acceso a tu cuenta de Yahoo! esta bloqueado. Por favor visita {0}
gateway.yahoo.unknownerror=No se pudo autenticar con la cuenta del mensajero de Yahoo!. (error desconocido)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=Transporte IRC
gateway.irc.username=Nombre de usuario
gateway.irc.password=Password
gateway.irc.nickname=Nickname
gateway.irc.registration=Por favor introduce tu nombre de usuario de IRC, password y nickname. El nickname es el nombre de usuario primario usado mientras que el nombre de usuario y password son usados para autenticar. Si no se requiere algun password dejalo en blanco.
gateway.irc.away=Ausente
gateway.irc.extendedaway=Ausencia Prolongada
gateway.irc.donotdisturb=No disponible
gateway.irc.errorreceived=Error IRC recibido:
gateway.irc.errorreceivedwithcode=Error IRC recibido (codigo {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=Selecciona cuales gateways estaran permitidos, que caracteristicas estaran disponibles y quien puede conectarse a cada servicio. Activando las casillas de los gateways, se activa el servicio.
gateway.web.settings.tests=Pruebas
gateway.web.settings.options=Opciones
gateway.web.settings.permissions=Permisos
gateway.web.settings.connecttohost=Conectar al host
gateway.web.settings.connecttoport=Conectar al puerto
gateway.web.settings.testconnection=Prueba de conexion
gateway.web.settings.saveoptions=Guardar Opciones
gateway.web.settings.cancelchanges=Cancelar cambios
gateway.web.settings.registernone=Unicamente inscripcion manual (ver la seccion de Inscripciones para administrar)
gateway.web.settings.registersome=Estos usuarios y/o grupos se pueden registrar.
gateway.web.settings.registerall=Todos los usuarios se pueden registrar.
gateway.web.settings.users=Usuarios
gateway.web.settings.groups=Grupos
gateway.web.settings.savepermissions=Guardar Permisos
gateway.web.settings.title=Configuraciones de Gateways
gateway.web.settings.settingssaved=Configuraciones guardadas
gateway.web.settings.cancelledchanges=Cambios cancelados
gateway.web.settings.success=Exitoso
gateway.web.settings.failed=Fallo
gateway.web.settings.permissionssaved=Permisos guardados
gateway.web.settings.host=Host
gateway.web.settings.port=Port
gateway.web.settings.encoding=Encoding
gateway.web.settings.unstable.title=Gateways experimentales.
gateway.web.settings.unstable.notice=Los siguientes gateways son experimentales y no se recomiendan en un ambiente de produccion. Se proveen para aquellos interesados en probar servicios de tipo no estable sabiendo de antemano que pueden no funcionar de manera correcta.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Abajo hay una lista de todas las posibles inscripciones a servicios de gateways. Para filtrar por sesiones activas y/o algun gateway en especifico selecciona las opciones de abajo y actualiza la vista.
gateway.web.registrations.addnewreg=Agregar una nueva inscripcion
gateway.web.registrations.cancelnewreg=Cancelar una nueva inscripcion
gateway.web.registrations.username=nombre de usuario
gateway.web.registrations.password=password
gateway.web.registrations.nickname=nickname
gateway.web.registrations.jid=usuario (JID)
gateway.web.registrations.gateway=gateway
gateway.web.registrations.signedon=Autenticado unicamente
gateway.web.registrations.update=Actualizar
gateway.web.registrations.next=Siguiente
gateway.web.registrations.prev=Anterior
gateway.web.registrations.remove=Remover
gateway.web.registrations.edit=Editar
gateway.web.registrations.lastlogin=Ultimo ingreso
gateway.web.registrations.serviceusername=Servicio/Nombre de usuario
gateway.web.registrations.user=Usuario
gateway.web.registrations.confirmdelete=Esta seguro que desea borrar esta inscripcion?
gateway.web.registrations.registrations=Inscripciones
gateway.web.registrations.title=Inscripciones a Gateways
gateway.web.registrations.xmppnotfound=Incapaz de encontrar la cuenta del usuario de XMPP.
gateway.web.registrations.regnotfound=Incapza de encontrar el registro.
gateway.web.registrations.notenabled=Transporte desactivado. Por favor activalo antes de intentar la operacion.
gateway.web.registrations.illegaldomain=El dominio de la cuenta del usuario XMPP no se encuentra en este servidor.
gateway.web.registrations.invaliduser=Nombre de usuario invalido para el servicio heredado.
gateway.web.registrations.deletesuccess=Registro eliminado exitosamente.
gateway.web.registrations.updatesuccess=Registro actualizado exitosamente.
gateway.web.registrations.addsuccess=Registro agregado exitosamente.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
##
## IM Gateway Resource Bundle - French locale (fr)
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=Admin Console
global.add=Ajouter
global.edit=Editer
global.cancel=Annuler
global.save_changes=Sauver Les Modifications
global.delete=Supprimer
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=Vous n'\u00cdtes pas entregistr\u00c8 pour le transport {0}.
gateway.base.enterusername=Entrez le nom {0} de la personne que vous voulez ajouter:
gateway.base.registrationdeniedbyacls=Votre inscription a \u00c8t\u00c8 refus\u00c8, votre compte n'a pas les droits d'acc\u00cbs.
gateway.base.registrationdeniedbyhost=Votre inscription a \u00c8t\u00c8 refus\u00c8e, votre compte n'existe pas sur le server du transport.
gateway.base.registrationdeniednoacct=Votre inscription a \u00c8t\u00c8 refus\u00c8e, vous n'avez pas de compte enregistr\u00c8 sur le server.
gateway.base.registrationdeniedbadusername=Votre inscription a \u00c8t\u00c8 refus\u00c8e, le nom sp\u00c8cifi\u00c8 n'est pas valide pour le service.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=La Connection a \u00c8chou\u00c8:
gateway.oscar.accountdeleted=CE compte a \u00c8t\u00c8 supprim\u00c8.
gateway.oscar.badinput=Format du Nom/login specifi\u00c8 invalide.
gateway.oscar.badpassword=Le Mot de passe sp\u00c8cifi\u00c8 est incorrect.
gateway.oscar.oldclient=LE plugin a \u00c8te identifi\u00c8 comme \u00c8tant un client obsol\u00cbte. Contactez le devloppeur SVP.
gateway.oscar.connectedtoomuch=Vous vous \u00cdtes connect\u00c8s trop souvent en un laps de temp court. Attendez 15 minutes avant de r\u00c8essayer SVP.
gateway.oscar.baduserorpass=L'identifiant ou le mot de passe specifi\u00c8 sont incorrects. Reessayez avec un login et mot de passe valides SVP.
gateway.oscar.accountsuspended=Votre compte a \u00c8t\u00c8 suspendu temporairement.
gateway.oscar.unknownerror=AIM Errreur de code inconnu:{0}\nURL: {1}
gateway.oscar.disconnected=Vous avez \u00c8t\u00c8 automatiquement d\u00c8connect\u00c8 par le serveur.
gateway.oscar.away=Pas l\u2021
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=AIM Transport
gateway.aim.username=Identifiant
gateway.aim.password=Mot de passe
gateway.aim.registration=Saisissez votre AIM Identifiant et mot de passe SVP.
gateway.aim.warninganon=Vous avez re\u00c1u une alerte anonyme de AIM. Votre niveau d'alerte est maintenant {0}%.
gateway.aim.warningdirect=Vous avez re\u00c1u une alerte AIM de {0}. Votre niveau d'alerte est maintenant {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=Transport ICQ
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Mot de passe
gateway.icq.registration=Entrez votre ICQ# (UIN) et mot de passe SVP.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=Transport MSN
gateway.msn.username=E-Mail Addresse
gateway.msn.password=Mot de passe
gateway.msn.registration=Entrez votre MSN e-mail addresse et mot de passe SVP.
gateway.msn.passwordincorrect=Le mot de passe sp\u00c8cifi\u00c8 n'est pas valide.Re-essayez avec un mot de passe valide SVP.
gateway.msn.sendmsgfailed=Impossible d'envoyer le message MSN. Raison:
gateway.msn.illegalaccount=Le format de l'identifiant sp\u00c8cifi\u00c8 pour le transport MSN n'est pas valide.\nL'identifiant doit \u00cdtre une adresse email.\nVous avez specifi\u00c8:
gateway.msn.disconnect=Vous avez \u00c3\u00a9t\u00c3\u00a9 d\u00c3\u00a9connect\u00c3\u00a9 du service MSN.
gateway.msn.wink=Vous avez re\u00c3\u00a7u une emoticon MSN.
gateway.msn.nudge=Vous avez re\u00c3\u00a7u un alerte sonore MSN.
gateway.msn.otherloggedin=Vous avez \u00c3\u00a9te d\u00c3\u00a9connect\u00c3\u00a9e d\u00e2\u0080\u0099MSN parce que vous \u00c3\u00aates d\u00c3\u00a9j\u00c3\u00a0 identifi\u00c3\u00a9 ailleurs.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Transport Yahoo!
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=Mot de passe
gateway.yahoo.registration=Entrez votre Yahoo! ID et mot de passe.
gateway.yahoo.error=Erreur Yahoo :
gateway.yahoo.mail=Vous avez {0} message(s) en attente dans votre boite mail Yahoo!.
gateway.yahoo.loginrefused=Echec de Log-in pour votre Yahoo! messenger compte.(login refus\u00c8)
gateway.yahoo.unknownuser=Yahoo! n'a pas reconnu le nom d'utilisateur que vous avez sp\u00c8cifi\u00c8.R\u00c8essayez avec Un ID valide SVP.
gateway.yahoo.badpassword=Login rejet\u00c8 par Yahoo!, peut \u00cdtre \u2021 cause d'un mot de passe incorrect.Re-essayez avec un mot de passe valide SVP.
gateway.yahoo.accountlocked=L'acces \u2021 votre compte Yahoo! est verrouill\u00c8.
gateway.yahoo.accountlockedwithurl=L'acces \u2021 votre compte Yahoo! est verrouill\u00c8.Allez sur {0} SVP
gateway.yahoo.unknownerror=Impossible de s'enregistrer sur votre compte Yahoo! messenger. (erreur inconnue)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=IRC Transport
gateway.irc.username=Identifiant
gateway.irc.password=Mot de passe
gateway.irc.nickname=Surnom
gateway.irc.registration=Saisissez votre Identifiant IRC, mot de passe et surnom SVP. Le Surnom est le nom utilis\u00c8 par IRC, tandis que l'Identifiant et le mot de passe sont utilis\u00c8s seulement pour la phase d'identification.Si vous n'avez pas de mot de passe, laissez le champs vide.
gateway.irc.away=Pas l\u2021
gateway.irc.extendedaway=De retour dans 5 min
gateway.irc.donotdisturb=Ne pas D\u00c8ranger
gateway.irc.errorreceived=Erreur re\u00c1ue d'IRC :
gateway.irc.errorreceivedwithcode=Erreur re\u00c1ue d'IRC (code {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=S\u00c8lectionnez les connections que vous voulez authorisez ainsi que les options disponibles et qui peut se connecter \u2021 chaque IM service. En cochant la connection, vous activez le service.
gateway.web.settings.tests=Tests
gateway.web.settings.options=Options
gateway.web.settings.permissions=Permissions
gateway.web.settings.connecttohost=Se Connecte au server
gateway.web.settings.connecttoport=Se Connecte au port
gateway.web.settings.testconnection=Testez la Connection
gateway.web.settings.saveoptions=Sauvegarder les Options
gateway.web.settings.cancelchanges=Annuler les Modifications
gateway.web.settings.registernone=Enregistrement manuel seulement (Voir la section des Enregistrements pour supervision)
gateway.web.settings.registersome=Ces utilisateurs et/ou groupes peuvent s'enregistrer
gateway.web.settings.registerall=Tous les utilisateurs peuvent s'enregistrer
gateway.web.settings.users=Utilisateurs
gateway.web.settings.groups=Groupes
gateway.web.settings.savepermissions=Sauvegarder les Permissions
gateway.web.settings.title=Gateway Configurations
gateway.web.settings.settingssaved=Configurations Sauvegard\u00c8es
gateway.web.settings.cancelledchanges=Modifications Annul\u00c8es
gateway.web.settings.success=R\u00c8ussi
gateway.web.settings.failed=Echec
gateway.web.settings.permissionssaved=Permissions Sauvegard\u00c8es
gateway.web.settings.host=Serveur
gateway.web.settings.port=Port
gateway.web.settings.encoding=Encodage
gateway.web.settings.unstable.title=Gateways Exp\u00c3\u00a9rimentales
gateway.web.settings.unstable.notice=Les Gateways suivantes sont exp\u00c3\u00a9rimentales et il est vivement d\u00c3\u00a9conseill\u00c3\u00a9 de les utiliser en environnement de production. Elles sont fournies pour les utilisateurs qui sont interess\u00c3\u00a9s par ces services instables et qui assument les risques li\u00c3\u00a9s \u00c3\u00a0 des dysfonctionnements potentiels.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Ci-dessous est la liste de tous les enregistrements aux diff\u00c8rentes Gateways. Pour filtrer par session active ou par gateway, selectionnez les options ci-dessous et mettez la vue \u2021 jour.
gateway.web.registrations.addnewreg=Ajouter un nouvel enregistrement
gateway.web.registrations.cancelnewreg=Annuler l'ajout d'un nouvel enregistrement
gateway.web.registrations.username=identifiant
gateway.web.registrations.password=mot de passe
gateway.web.registrations.nickname=surnom
gateway.web.registrations.jid=user (JID)
gateway.web.registrations.gateway=gateway
gateway.web.registrations.signedon=Enregistr\u00c8 seulement
gateway.web.registrations.update=Mise \u2021 jour
gateway.web.registrations.next=Suivant
gateway.web.registrations.prev=Pr\u00c8c\u00c8dent
gateway.web.registrations.remove=Supprimer
gateway.web.registrations.edit=Editer
gateway.web.registrations.lastlogin=Dernier Login
gateway.web.registrations.serviceusername=Service/Identifiant
gateway.web.registrations.user=Utilisateur
gateway.web.registrations.confirmdelete=Etes vous s\u02dar de vouloir supprimer cet enregistrement ?
gateway.web.registrations.registrations=Enregistrements
gateway.web.registrations.title=Gateway Enregistrements
gateway.web.registrations.xmppnotfound=Impossible de retrouver votre compte utilisateur XMPP.
gateway.web.registrations.regnotfound=Impossible de retrouver votre inscription.
gateway.web.registrations.notenabled=Le Transport n\u00e2\u0080\u0099est pas actif. Activez le transport SVP et retentez l\u00e2\u0080\u0099op\u00c3\u00a9ration.
gateway.web.registrations.illegaldomain=Le domaine du compte XMPP n\u00e2\u0080\u0099appartient pas \u00c3\u00a0 ce serveur.
gateway.web.registrations.invaliduser=L\u00e2\u0080\u0099identifiant sp\u00c3\u00a9cifi\u00c3\u00a9 est invalide pour le service.
gateway.web.registrations.deletesuccess=L\u00e2\u0080\u0099inscription a bien \u00c3\u00a9t\u00c3\u00a9 supprim\u00c3\u00a9e.
gateway.web.registrations.updatesuccess= L\u00e2\u0080\u0099inscription a bien \u00c3\u00a9t\u00c3\u00a9 mise \u00c3\u00a0 jour.
gateway.web.registrations.addsuccess= L\u00e2\u0080\u0099inscription a bien \u00c3\u00a9t\u00c3\u00a9 ajout\u00c3\u00a9e.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
##
## IM Gateway Resource Bundle - Italian locale (it)
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=Console Amministrativa
global.add=Aggiungi
global.edit=Modifica
global.delete=Elimina
global.cancel=Cancella
global.save_changes=Salva le modifiche
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=In questo momento non sei loggato nel trasporto {0}.
gateway.base.enterusername=Prego inserire {0} lo username della persona che vuoi aggiungere.
gateway.base.registrationdeniedbyacls=La registrazione \u00c3\u00a8 stata rifiutata perch\u00c3\u00a8 l'account non \u00c3\u00a8 nella lista di accesso.
gateway.base.registrationdeniedbyhost=La registrazione \u00c3\u00a8 stata rifiutata perch\u00c3\u00a8 l'account non esiste nel server di trasporto.
gateway.base.registrationdeniednoacct=La registrazione \u00c3\u00a8 stata rifiutata perch\u00c3\u00a8 non hai un account registrato nel server.
gateway.base.registrationdeniedbadusername=La registrazione \u00c3\u00a8 stata rifiutata perch\u00c3\u00a8 lo username che hai inserito non \u00c3\u00a8 valido per il servizio.
# OSCAR 'Global' (both AIM/ICQ Transport)
gateway.oscar.connectionfailed=Connessione fallita:
gateway.oscar.accountdeleted=L'account \u00c3\u00a8 stato cancellato.
gateway.oscar.badinput=Inserito uno username non valido.
gateway.oscar.badpassword=Password non corretta.
gateway.oscar.oldclient=Il Plugin si \u00c3\u00a8 definito come obsoleto. Contattare lo sviluppatore.
gateway.oscar.connectedtoomuch=Ti sei connesso troppe volte nell'arco di tempo previsto. Per favore attendi almeno 15 minuti prima di riprovare.
gateway.oscar.baduserorpass=Nome utente o password non validi. Reinserirli.
gateway.oscar.accountsuspended=Il tuo account \u00c3\u00a8 stato temporaneamente sospeso.
gateway.oscar.unknownerror=Codice di errore sconosciuto ricevuto da AIM: {0}\nURL: {1}
gateway.oscar.disconnected=Sei stato disconnesso automaticamente dal server.
gateway.oscar.away=Away
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=Trasporto AIM
gateway.aim.username=Username
gateway.aim.password=Password
gateway.aim.registration=Inserire username e password per AIM.
gateway.aim.warninganon=Hai ricevuto una notifica di anonimit\u00c3\u00a0 da AIM. Il tuo livello di attenzione \u00c3\u00a8 ora {0}%.
gateway.aim.warningdirect=Hai ricevuto una notifica di warning da AIM {0}. Il tuo livello di attenzione \u00c3\u00a8 ora {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=Trasporto ICQ
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Password
gateway.icq.registration=Inserire utente e password per ICQ# (UIN).
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=Trasporto MSN
gateway.msn.username=Indirizzo E-Mail
gateway.msn.password=Password
gateway.msn.registration=Inserire il tuo account e password per MSN Passport.
gateway.msn.passwordincorrect=La password con cui ti sei registrato non \u00c3\u00a8 corretta. Reinserirla.
gateway.msn.sendmsgfailed=Impossibile inviare messaggi MSN. Motivo:
gateway.msn.illegalaccount=Sei registrato al trasporto MSN con un account non valido.\nL'account dovrebbe essere un indirizzo email.\nSei registrato come:
gateway.msn.disconnect=Sei stato disconnesso da MSN.
gateway.msn.wink=Hai ricevuto un wink da MSN.
gateway.msn.nudge=Hai ricevuto un nudge da MSN.
gateway.msn.otherloggedin=Sei stato disconnesso da MSN perch\u00c3\u00a8 il tuo account si \u00c3\u00a8 registrato altrove.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Trasporto Yahoo!
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=Password
gateway.yahoo.registration=Inserire ID e password per Yahoo!.
gateway.yahoo.error=Errore da Yahoo:
gateway.yahoo.mail=Hai {0} messaggio(i) su Yahoo! mail.
gateway.yahoo.loginrefused=Tentativo di accesso fallito su Yahoo!. (login rifiutato)
gateway.yahoo.unknownuser=Yahoo! non ha riconosciuto lo username con cui ti sei registrato. Inserire lo username corretto.
gateway.yahoo.badpassword=Login refiutato da Yahoo!, forse per un errore di password. Inserire la password corretta.
gateway.yahoo.accountlocked=L'accesso al tuo Yahoo! account \u00c3\u00a8 bloccato.
gateway.yahoo.accountlockedwithurl=L'accesso al tuo Yahoo! account \u00c3\u00a8 bloccato. Visitare {0}
gateway.yahoo.unknownerror=Login fallito a Yahoo! messenger account. (errore sconosciuto)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=Trasporto IRC
gateway.irc.username=Username
gateway.irc.password=Password
gateway.irc.nickname=Nickname
gateway.irc.registration=Inserire username, password e nickname per IRC. Il Nickname \u00c3\u00a8 lo username primario usato mentre username e password sono usati per l'autenticazione. Se la password non \u00c3\u00a8 richiesta, non inserirla.
gateway.irc.away=Away
gateway.irc.extendedaway=Away Esteso
gateway.irc.donotdisturb=Non Disturbare
gateway.irc.errorreceived=Errore IRC ricevuto:
gateway.irc.errorreceivedwithcode=Errore IRC ricevuto (code {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=Seleziona quale gateway permettere, quali opzioni disponibili, e chi si pu\u00c3\u00b2 connettere a ciascun servizio. Selezionare un gateway abilita il servizio stesso.
gateway.web.settings.tests=Tests
gateway.web.settings.options=Opzioni
gateway.web.settings.permissions=Permessi
gateway.web.settings.connecttohost=Connetti all'host
gateway.web.settings.connecttoport=Connetti alla porta
gateway.web.settings.testconnection=Test di Connessione
gateway.web.settings.saveoptions=Opzioni di Salvataggio
gateway.web.settings.cancelchanges=Scarta i cambiamenti
gateway.web.settings.registernone=Solo Registrazione Manuale (esamina la sezioni sulle registrazioni nella manpage)
gateway.web.settings.registersome=Questi utenti/gruppi possono registrarsi
gateway.web.settings.registerall=Tutti gli utenti possono registrarsi
gateway.web.settings.users=Utenti
gateway.web.settings.groups=Gruppi
gateway.web.settings.savepermissions=Permessi di salvataggio
gateway.web.settings.title=Opzioni del Gateway
gateway.web.settings.settingssaved=Opzioni salvate
gateway.web.settings.cancelledchanges=Cambiamenti scartati
gateway.web.settings.success=Successo
gateway.web.settings.failed=Faillito
gateway.web.settings.permissionssaved=Permessi salvati
gateway.web.settings.host=Host
gateway.web.settings.port=Porta
gateway.web.settings.encoding=Encoding
gateway.web.settings.unstable.title=Gateways sperimentali
gateway.web.settings.unstable.notice=I seguenti gateways sono sperimentali e non raccomandati in ambienti di produzione. Essi sono forniti con l'intento di provare servizi non stabili e non funzionanti nella maniera corretta.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Sotto troverete la lista di tutti i gateway di registrazione. Se intendete filtrarli per sessioni attive e/o per specifico gateway seleziona le opzioni qui sotto e aggiorna la visualizzazione.
gateway.web.registrations.addnewreg=Aggiungi una nuova registrazione
gateway.web.registrations.cancelnewreg=Scarta l'aggiunta di una nuova registrazione
gateway.web.registrations.username=username
gateway.web.registrations.password=password
gateway.web.registrations.nickname=nickname
gateway.web.registrations.jid=utente (JID)
gateway.web.registrations.gateway=gateway
gateway.web.registrations.signedon=Registrato solamente
gateway.web.registrations.update=Aggiorna
gateway.web.registrations.next=Successivo
gateway.web.registrations.prev=Precedente
gateway.web.registrations.remove=Elimina
gateway.web.registrations.edit=Modifica
gateway.web.registrations.lastlogin=Ultimo Login
gateway.web.registrations.serviceusername=Servizio/Username
gateway.web.registrations.user=Utente
gateway.web.registrations.confirmdelete=Sei sicuro di voler eliminare la registrazione?
gateway.web.registrations.registrations=Registrazioni
gateway.web.registrations.title=Gateway Registrazioni
gateway.web.registrations.xmppnotfound=Impossibile trovare l'account XMPP.
gateway.web.registrations.regnotfound=Impossibile trovare la registrazione.
gateway.web.registrations.notenabled=Il trasporto non \u00c3\u00a8 abilitato. Abilitarlo prima di procedere ulteriormente.
gateway.web.registrations.illegaldomain=L'account XMPP non \u00c3\u00a8 in questo server.
gateway.web.registrations.invaliduser=Username non valido per questo servizio.
gateway.web.registrations.deletesuccess=Registrazione eliminata correttamente.
gateway.web.registrations.updatesuccess=Registrazione aggiornata correttamente.
gateway.web.registrations.addsuccess=Registrazione aggiunta correttamente.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
##
## IM Gateway Resource Bundle - Brazillian Portuguese locale (pt_BR)
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=Console Administrativo
global.add=Adicionar
global.edit=Editar
global.cancel=Cancelar
global.save_changes=Salvar mudan\u00e7as
global.delete=Apagar
# Globals
gateway.name=IM Gateway
gateway.description=Provides gateway connectivity to the other public instant messaging networks
gateway.gateways=Gateways
gateway.gateways.desc=Gateway setup
gateway.settings=Settings
gateway.settings.desc=Click to manage the service that provides access to other IM networks
gateway.registrations=Registrations
gateway.registrations.desc=Click to view and manage the user registrations to other IM networks
# Base Transport
gateway.base.notloggedin=Voc\u00ea n\u00e3o est\u00e1 atualmente conectado no transporte {0}.
gateway.base.enterusername=Por favor coloque o nome do usu\u00e1rio do {0} da pessoa que voc\u00ea quer adicionar.
gateway.base.registrationdeniedbyacls=Seu registro foi negado pois a sua conta n\u00e3o se encontra na lista de acesso.
gateway.base.registrationdeniedbyhost=Seu registro foi negado pois a sua conta n\u00e3o pertence ao mesmo servidor do transporte.
gateway.base.registrationdeniednoacct=Seu registro foi negado porque voc\u00ea n\u00e3o possui uma conta no servidor.
gateway.base.registrationdeniedbadusername=Seu registro foi negado pois o usu\u00e1rio fornecido n\u00e3o \u00e9 v\u00e1lido para o servi\u00e7o.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=Conex\u00e3o falhou:
gateway.oscar.accountdeleted=Este conta foi apagada.
gateway.oscar.badinput=Nome/UIN ilegal.
gateway.oscar.badpassword=Senha incorreta.
gateway.oscar.oldclient=O plugin se identificou como muito antigo do cliente. Por favor contate o desenvolvedor.
gateway.oscar.connectedtoomuch=Voc\u00ea conectou muitas vezes em um curto per\u00edodo de tempo. Por favor espere cerca de 15 minutos para se conectar novamente.
gateway.oscar.baduserorpass=Nome do usu\u00e1rio ou senha inv\u00e1lido. Por favor se registre novamente com um nome do usu\u00e1rio e senha v\u00e1lidos.
gateway.oscar.accountsuspended=Sua conta foi temporariamente suspensa.
gateway.oscar.unknownerror=C\u00f3dito de retorno de erro desconhecido do AIM: {0}\nURL: {1}
gateway.oscar.disconnected=Voc\u00ea foi desconectado autom\u00e1ticamente pelo servidor.
gateway.oscar.away=Fora
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=AIM Transport
gateway.aim.username=Nome do Usu\u00e1rio
gateway.aim.password=Senha
gateway.aim.registration=Por favor entre com o nome do usu\u00e1rio e a senhado AIM.
gateway.aim.warninganon=Voc\u00ea recebeu um aviso an\u00f4nimo do AIM. Seu n\u00edvel de aviso agora \u00e9 {0}%.
gateway.aim.warningdirect=Voc\u00ea recebeu um aviso AIM de {0}. Seu n\u00edvel de aviso agora \u00e9 {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=ICQ Transport
gateway.icq.username=UIN/ICQ#
gateway.icq.password=Senha
gateway.icq.registration=Por favor entre com o seu ICQ# (UIN) e a senha.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=Transporte MSN
gateway.msn.username=Endere\u00e7o de E-Mail
gateway.msn.password=Senha
gateway.msn.registration=Por favor entre com o seu e-mail do MSN Passport e a senha.
gateway.msn.passwordincorrect=A senha com que voc\u00ea se registrou est\u00e1 errada. Por favor se registre novamente com a senha certa.
gateway.msn.sendmsgfailed=N\u00e3o foi poss\u00edvel mandar uma mensagem MSN. Raz\u00e3o:
gateway.msn.illegalaccount=Voc\u00ea est\u00e1 registrado no Transporte MSN com uma conta inv\u00e1lida.\nO nome da conta deve ser um endere\u00e7o de e-mail.\nVoc\u00ea se registrou como:
gateway.msn.disconnect=oc\u00c3\u00aa foi desconectado do servi\u00c3\u00a7o do MSN.
gateway.msn.wink=Voc\u00c3\u00aa recebeu um wink MSN.
gateway.msn.nudge=Voc\u00c3\u00aa recebeu um pedido de aten\u00c3\u00a7\u00c3\u00a3o no MSN.
gateway.msn.otherloggedin=Voc\u00c3\u00aa foi desconectado do MSN porque a sua conta foi conectada em outro local.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Trnasporte Yahoo!
gateway.yahoo.username=ID Yahoo!
gateway.yahoo.password=Senha
gateway.yahoo.registration=Por favor entre com o seu ID Yahoo! e a senha.
gateway.yahoo.error=Erro do Yahoo:
gateway.yahoo.mail=Voc\u00ea tem {0} mensagem(ns) esperando por voc\u00ea no e-mail Yahoo!.
gateway.yahoo.loginrefused=Falha ao conectar na sua conta no Yahoo! messenger. (login recusado)
gateway.yahoo.unknownuser=O Yahoo! n\u00e3o reconheceu o nome do usu\u00e1rio que voc\u00ea se registrou. Por favor se registre novamente com o nome do usu\u00e1rio correto.
gateway.yahoo.badpassword=Login recusado pelo Yahoo!, talvez pela senha errada. Por favor se registre novamente com a senha correta.
gateway.yahoo.accountlocked=O acesso \u00e0 sua conta do Yahoo! est\u00e1 bloqueado.
gateway.yahoo.accountlockedwithurl=O acesso \u00e0 sua conta do Yahoo! est\u00e1 bloqueado. Por favor veja {0}
gateway.yahoo.unknownerror=Falha ao se conectar na sua conta do Yahoo! messenger. (erro desconhecido)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=Transporte IRC
gateway.irc.username=Nome do usu\u00e1rio
gateway.irc.password=Senha
gateway.irc.nickname=Nick
gateway.irc.registration=Por favor entre com o seu nome do usu\u00e1rio do IRC, senha, e nick. Nick \u00e9 o nome do usu\u00e1rio prim\u00e1rio, enquanto o nome do usu\u00e1rio e senha s\u00e3o usados para autentica\u00e7\u00e3o. Se n\u00e3o for obrigat\u00f3rio uma senha, deixe-a em branco.
gateway.irc.away=Fora
gateway.irc.extendedaway=Fora por tempo Extendido
gateway.irc.donotdisturb=N\u00e3o Perturbe
gateway.irc.errorreceived=Erro IRC recebido:
gateway.irc.errorreceivedwithcode=Erro IRC recebido (c\u00f3digo {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP Transport
gateway.xmpp.username=JID
gateway.xmpp.password=Password
gateway.xmpp.registration=Please enter your XMPP JID and password as it's used on the XMPP server pointed to by the transport.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk Transport
gateway.gtalk.username=Address
gateway.gtalk.registration=Please enter your e-mail address and password used with GMail and GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=Selecione quais gateways ser\u00e3o permitidos, quais caracter\u00edsticas ser\u00e3o dispon\u00edveis, e quem pode conectar em cada servi\u00e7o do gateway. Marcando um gateway habilita o servi\u00e7o.
gateway.web.settings.tests=Testes
gateway.web.settings.options=Op\u00e7\u00f5es
gateway.web.settings.permissions=Permiss\u00f5es
gateway.web.settings.connecttohost=Conectar no host
gateway.web.settings.connecttoport=Conectar na porta
gateway.web.settings.testconnection=Testar conex\u00e3o
gateway.web.settings.saveoptions=Salvar Op\u00e7\u00f5es
gateway.web.settings.cancelchanges=Cancel Changes
gateway.web.settings.registernone=Somente registro manual (veja a se\u00e7\u00e3o Registros para controlar)
gateway.web.settings.registersome=Esses usu\u00e1rios e/ou grupos podem se registrar
gateway.web.settings.registerall=Todos os usu\u00e1rios podem se registrar
gateway.web.settings.users=Usu\u00e1rios
gateway.web.settings.groups=Grupos
gateway.web.settings.savepermissions=Salvar Permiss\u00f5es
gateway.web.settings.title=Op\u00e7\u00f5es do Gateway
gateway.web.settings.settingssaved=Op\u00e7\u00f5es Salvas
gateway.web.settings.cancelledchanges=Mudan\u00e7as Canceladas
gateway.web.settings.success=Sucesso
gateway.web.settings.failed=Falhou
gateway.web.settings.permissionssaved=Permiss\u00f5es Salvas
gateway.web.settings.host=Host
gateway.web.settings.port=Porta
gateway.web.settings.encoding=Codifica\u00e7\u00e3o
gateway.web.settings.unstable.title=Gateways Experimentais
gateway.web.settings.unstable.notice=Os gateways a seguir s\u00c3\u00a3o experimentais e n\u00c3\u00a3o s\u00c3\u00a3o recomendados em um ambiente de produ\u00c3\u00a7\u00c3\u00a3o. Eles s\u00c3\u00a3o fornecidos para aqueles interessados em testar servi\u00c3\u00a7os inst\u00c3\u00a1veis e est\u00c3\u00a3o confort\u00c3\u00a1veis sabendo que podem n\u00c3\u00a3o funcionar corretamente.
# Web Interface (Registrations)
gateway.web.registrations.instructions=Abaixo est\u00e1 a lista de todos os registros nos servi\u00e7os do gateway. Para filtrar por sess\u00f5es ativas e/ou gateways espec\u00edficos, selecione as op\u00e7\u00f5es abaixo e atualize a lista.
gateway.web.registrations.addnewreg=Adicionar um novo registro
gateway.web.registrations.cancelnewreg=Cancelar a adi\u00e7\u00e3o de um novo registro
gateway.web.registrations.username=usu\u00e1rio
gateway.web.registrations.password=senha
gateway.web.registrations.nickname=apelido
gateway.web.registrations.jid=usu\u00e1rio (JID)
gateway.web.registrations.gateway=gateway
gateway.web.registrations.signedon=Somente os marcados
gateway.web.registrations.update=Atualizar
gateway.web.registrations.next=Pr\u00f3ximo
gateway.web.registrations.prev=Anterior
gateway.web.registrations.remove=Remover
gateway.web.registrations.edit=Editar
gateway.web.registrations.lastlogin=\u00daltimo Login
gateway.web.registrations.serviceusername=Servi\u00e7o/Nome do Usu\u00e1rio
gateway.web.registrations.user=Usu\u00e1rio
gateway.web.registrations.confirmdelete=Voc\u00ea tem certeza que deseja apagar este registro?
gateway.web.registrations.registrations=Registros
gateway.web.registrations.title=Registros do Gateway
gateway.web.registrations.xmppnotfound=Incapaz de achar a conta do usu\u00c3\u00a1rio XMPP.
gateway.web.registrations.regnotfound=Incapaz de encontrar o registro.
gateway.web.registrations.notenabled=Transporte n\u00c3\u00a3o est\u00c3\u00a1 habilitado. Por favor o habilite antes de tentar esta opera\u00c3\u00a7\u00c3\u00a3o.
gateway.web.registrations.illegaldomain=O dom\u00c3\u00adnio da conta do usu\u00c3\u00a1rio XMPP n\u00c3\u00a3o \u00c3\u00a9 neste servidor.
gateway.web.registrations.invaliduser=Nome do usu\u00c3\u00a1rio inv\u00c3\u00a1lido para o servi\u00c3\u00a7o.
gateway.web.registrations.deletesuccess=Registro apagado com sucesso.
gateway.web.registrations.updatesuccess=Registro atualizado com sucesso.
gateway.web.registrations.addsuccess=Registro adicionado com sucesso.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
##
## IM Gateway Resource Bundle - Russian UTF-8 Locale
##
## For a full changelog, refer to the English bundle, gateway_i18n.properties.
# Temporary Tags Until Fixed Properly
login.title=\u0430\u009a\u0430\u041e\u0430\u041d\u0431\u0081\u0430\u041e\u0430\u041b\u0431\u008c \u0430\u0090\u0430\u0414\u0430\u041c\u0430\u0418\u0430\u041d\u0430\u0410
global.add=\u0430\u0094\u0430\u041e\u0430\u0411\u0430\u0410\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c
global.edit=\u0430\u0098\u0430\u0417\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c
global.delete=\u0430\u0403\u0430\u0414\u0430\u0410\u0430\u041b\u0430\u0418\u0431\u0082\u0431\u008c
global.cancel=\u0430\u009e\u0431\u0082\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c
global.save_changes=\u0430\u0401\u0430\u041e\u0431\u0085\u0431\u0080\u0430\u0410\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u0098\u0430\u0417\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f
# Globals
gateway.name=IM \u0430\u0408\u0430\u041b\u0431\u008e\u0430\u0417
gateway.description=\u0430\u009f\u0430\u041e\u0430\u0417\u0430\u0412\u0430\u041e\u0430\u041b\u0431\u008f\u0430\u0415\u0431\u0082 \u0431\u0081\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0431\u008f\u0431\u0082\u0431\u008c\u0431\u0081\u0431\u008f \u0431\u0087\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0417 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417 \u0431\u0081 \u0430\u0414\u0431\u0080\u0431\u0083\u0430\u0413\u0430\u0418\u0430\u041c\u0430\u0418 \u0430\u041f\u0431\u0083\u0430\u0411\u0430\u041b\u0430\u0418\u0431\u0087\u0430\u041d\u0431\u008b\u0430\u041c\u0430\u0418 IM \u0431\u0081\u0430\u0415\u0431\u0082\u0431\u008f\u0430\u041c\u0430\u0418
gateway.gateways=\u0430\u0408\u0430\u041b\u0431\u008e\u0430\u0417\u0431\u008b
gateway.gateways.desc=\u0430\u009d\u0430\u0410\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u041e\u0430\u0419\u0430\u041a\u0430\u0410 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u0410
gateway.settings=\u0430\u0403\u0431\u0081\u0431\u0082\u0430\u0410\u0430\u041d\u0430\u041e\u0430\u0412\u0430\u041a\u0430\u0418
gateway.settings.desc=\u0430\u009d\u0430\u0410\u0430\u0416\u0430\u041c\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0414\u0430\u041b\u0431\u008f \u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0430\u041e\u0430\u041c \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0410 \u0430\u041a \u0430\u0414\u0431\u0080\u0431\u0083\u0430\u0413\u0430\u0418\u0430\u041c IM \u0431\u0081\u0430\u0415\u0431\u0082\u0431\u008f\u0430\u041c
gateway.registrations=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418
gateway.registrations.desc=\u0430\u009d\u0430\u0410\u0430\u0416\u0430\u041c\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0414\u0430\u041b\u0431\u008f \u0430\u041f\u0431\u0080\u0430\u041e\u0431\u0081\u0430\u041c\u0430\u041e\u0431\u0082\u0431\u0080\u0430\u0410 \u0430\u0418 \u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f\u0430\u041c\u0430\u0418 \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0430\u0415\u0430\u0419 \u0430\u0414\u0431\u0080\u0431\u0083\u0430\u0413\u0430\u0418\u0431\u0085 IM \u0431\u0081\u0430\u0415\u0431\u0082\u0430\u0415\u0430\u0419
# Base Transport
gateway.base.notloggedin=\u0430\u0092 \u0430\u0414\u0430\u0410\u0430\u041d\u0430\u041d\u0431\u008b\u0430\u0419 \u0430\u041c\u0430\u041e\u0430\u041c\u0430\u0415\u0430\u041d\u0431\u0082 \u0430\u0412\u0431\u008b \u0430\u041d\u0430\u0415 \u0430\u0412\u0430\u041e\u0431\u0088\u0430\u041b\u0430\u0418 \u0430\u0412 {0} transport.
gateway.base.enterusername=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 {0} \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f \u0430\u041f\u0430\u0415\u0431\u0080\u0431\u0081\u0430\u041e\u0430\u041d\u0431\u008b, \u0430\u041a\u0430\u041e\u0431\u0082\u0430\u041e\u0431\u0080\u0431\u0083\u0431\u008e \u0431\u0085\u0430\u041e\u0431\u0082\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0414\u0430\u041e\u0430\u0411\u0430\u0410\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c.
gateway.base.registrationdeniedbyacls=\u0430\u0092\u0430\u0410\u0431\u0088\u0430\u0410 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0410, \u0431\u0082\u0430\u0410\u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0412\u0431\u008b \u0430\u041d\u0430\u0415 \u0430\u041f\u0431\u0080\u0430\u041e\u0430\u041f\u0430\u0418\u0431\u0081\u0430\u0410\u0430\u041d\u0431\u008b \u0430\u0412 \u0431\u0081\u0430\u041f\u0430\u0418\u0431\u0081\u0430\u041a\u0430\u0415 \u0431\u0080\u0430\u0410\u0430\u0417\u0431\u0080\u0430\u0415\u0431\u0088\u0430\u0415\u0430\u041d\u0430\u041d\u0431\u008b\u0431\u0085 \u0430\u0414\u0430\u041b\u0431\u008f \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0410.
gateway.base.registrationdeniedbyhost=\u0430\u0092\u0430\u0410\u0431\u0088\u0430\u0410 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0410, \u0431\u0082\u0430\u0410\u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0412\u0431\u008b \u0430\u041d\u0430\u0415 \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d\u0431\u008b \u0430\u041d\u0430\u0410 \u0431\u0082\u0430\u041e\u0430\u041c \u0430\u0416\u0430\u0415 \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u0415, \u0430\u041d\u0430\u0410 \u0430\u041a\u0430\u041e\u0431\u0082\u0430\u041e\u0431\u0080\u0430\u041e\u0430\u041c \u0430\u041d\u0430\u0410\u0431\u0085\u0430\u041e\u0430\u0414\u0430\u0418\u0431\u0082\u0431\u0081\u0431\u008f \u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082.
gateway.base.registrationdeniednoacct=\u0430\u0092\u0430\u0410\u0431\u0088\u0430\u0410 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0410, \u0431\u0082\u0430\u0410\u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0412\u0431\u008b \u0430\u041d\u0430\u0415 \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d\u0431\u008b \u0430\u041d\u0430\u0410 \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u0415.
gateway.base.registrationdeniedbadusername=\u0430\u0092\u0430\u0410\u0431\u0088\u0430\u0410 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0410, \u0431\u0082\u0430\u0410\u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f, \u0430\u041a\u0430\u041e\u0431\u0082\u0430\u041e\u0431\u0080\u0430\u041e\u0430\u0415 \u0430\u0412\u0431\u008b \u0431\u0083\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041b\u0430\u0418 \u0430\u041d\u0430\u0415\u0430\u041f\u0431\u0080\u0430\u0418\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u041c\u0430\u041e \u0430\u0414\u0430\u041b\u0431\u008f \u0431\u008d\u0431\u0082\u0430\u041e\u0430\u0413\u0430\u041e \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0430\u0410.
# OSCAR 'Global' (both AIM/ICQ Transports)
gateway.oscar.connectionfailed=\u0430\u009d\u0430\u0415\u0431\u0082 \u0431\u0081\u0430\u0412\u0431\u008f\u0430\u0417\u0430\u0418:
gateway.oscar.accountdeleted=\u0430\u00ad\u0431\u0082\u0430\u041e\u0431\u0082 \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082 \u0431\u0083\u0430\u0414\u0430\u0410\u0430\u041b\u0430\u0415\u0430\u041d.
gateway.oscar.badinput=\u0430\u0403\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041d\u0430\u041e \u0430\u041d\u0430\u0415\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041d\u0430\u041e\u0430\u0415 screen name/uin.
gateway.oscar.badpassword=\u0430\u0403\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041d \u0430\u041d\u0430\u0415\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041d\u0431\u008b\u0430\u0419 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c.
gateway.oscar.oldclient=\u0430\u009f\u0430\u041b\u0430\u0410\u0430\u0413\u0430\u0418\u0430\u041d \u0430\u0418\u0430\u0414\u0430\u0415\u0430\u041d\u0431\u0082\u0430\u0418\u0431\u0084\u0430\u0418\u0431\u0086\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d \u0430\u041a\u0430\u0410\u0430\u041a \u0431\u0081\u0430\u041b\u0430\u0418\u0431\u0088\u0430\u041a\u0430\u041e\u0430\u041c \u0431\u0081\u0431\u0082\u0430\u0410\u0431\u0080\u0431\u008b\u0430\u0419 \u0430\u041a\u0430\u041b\u0430\u0418\u0430\u0415\u0430\u041d\u0431\u0082. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0431\u0081\u0430\u0412\u0431\u008f\u0430\u0416\u0430\u0418\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u008c \u0431\u0081 \u0431\u0080\u0430\u0410\u0430\u0417\u0431\u0080\u0430\u0410\u0430\u0411\u0430\u041e\u0431\u0082\u0431\u0087\u0430\u0418\u0430\u041a\u0430\u041e\u0430\u041c.
gateway.oscar.connectedtoomuch=\u0430\u0092\u0431\u008b \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0431\u0081\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0431\u008f\u0430\u041b\u0430\u0418\u0431\u0081\u0431\u008c \u0431\u0081\u0430\u041b\u0430\u0418\u0431\u0088\u0430\u041a\u0430\u041e\u0430\u041c \u0430\u041c\u0430\u041d\u0430\u041e\u0430\u0413\u0430\u041e \u0431\u0080\u0430\u0410\u0430\u0417 \u0430\u0417\u0430\u0410 \u0430\u041a\u0430\u041e\u0431\u0080\u0430\u041e\u0431\u0082\u0430\u041a\u0430\u0418\u0430\u0419 \u0430\u041f\u0431\u0080\u0430\u041e\u0430\u041c\u0430\u0415\u0430\u0416\u0431\u0083\u0431\u0082\u0430\u041e\u0430\u041a \u0430\u0412\u0431\u0080\u0430\u0415\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u041f\u0430\u041e\u0430\u0414\u0430\u041e\u0430\u0416\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 15 \u0430\u041c\u0430\u0418\u0430\u041d\u0431\u0083\u0431\u0082 \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0414 \u0430\u041f\u0430\u041e\u0430\u0412\u0431\u0082\u0430\u041e\u0431\u0080\u0430\u041d\u0430\u041e\u0430\u0419 \u0430\u041f\u0430\u041e\u0430\u041f\u0431\u008b\u0431\u0082\u0430\u041a\u0430\u041e\u0430\u0419.
gateway.oscar.baduserorpass=\u0430\u0403\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041d\u0431\u008b \u0430\u041d\u0430\u0415\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041d\u0431\u008b\u0430\u0415 screen name \u0430\u0418\u0430\u041b\u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0431\u0083\u0430\u0419\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u008c \u0431\u0081 \u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041d\u0431\u008b\u0430\u041c\u0430\u0418 screen name \u0430\u0418\u0430\u041b\u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0430\u0415\u0430\u041c.
gateway.oscar.accountsuspended=\u0430\u0092\u0430\u0410\u0431\u0088 \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082 \u0430\u0411\u0431\u008b\u0430\u041b \u0430\u0412\u0431\u0080\u0430\u0415\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u041d\u0430\u041e \u0430\u0417\u0430\u0410\u0430\u0411\u0430\u041b\u0430\u041e\u0430\u041a\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d.
gateway.oscar.unknownerror=\u0430\u009d\u0430\u0415\u0430\u0418\u0430\u0417\u0430\u0412\u0430\u0415\u0431\u0081\u0431\u0082\u0430\u041d\u0431\u008b\u0430\u0419 \u0430\u041a\u0430\u041e\u0430\u0414 \u0430\u041e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0418 \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0415\u0430\u041d \u0430\u041e\u0431\u0082 AIM: {0}\nURL: {1}
gateway.oscar.disconnected=\u0430\u0092\u0431\u008b \u0430\u0411\u0431\u008b\u0430\u041b\u0430\u0418 \u0430\u0410\u0430\u0412\u0431\u0082\u0430\u041e\u0430\u041c\u0430\u0410\u0431\u0082\u0430\u0418\u0431\u0087\u0430\u0415\u0431\u0081\u0430\u041a\u0430\u0418 \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0431\u008e\u0431\u0087\u0430\u0415\u0430\u041d\u0431\u008b \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041e\u0430\u041c.
gateway.oscar.away=\u0430\u009e\u0431\u0082\u0430\u041e\u0431\u0088\u0430\u0415\u0430\u041b
# AIM Transport
gateway.aim.shortservice=AIM
gateway.aim.service=AOL Instant Messenger
gateway.aim.name=AIM \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.aim.username=ScreenName
gateway.aim.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.aim.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 AIM ScreenName \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c.
gateway.aim.warninganon=\u0430\u0092\u0431\u008b \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0418\u0430\u041b\u0430\u0418 \u0430\u0410\u0430\u041d\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c\u0430\u041d\u0430\u041e\u0430\u0415 AIM \u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0416\u0430\u0414\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0415. \u0430\u0092\u0430\u0410\u0431\u0088 \u0431\u0083\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0415\u0430\u041d\u0431\u008c \u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0416\u0430\u0414\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0419 \u0431\u0082\u0430\u0415\u0430\u041f\u0430\u0415\u0431\u0080\u0431\u008c {0}%.
gateway.aim.warningdirect=\u0430\u0092\u0431\u008b \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0418\u0430\u041b\u0430\u0418 AIM \u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0416\u0430\u0414\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0415 \u0430\u041e\u0431\u0082 {0}. \u0430\u0092\u0430\u0410\u0431\u0088 \u0431\u0083\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0415\u0430\u041d\u0431\u008c \u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0416\u0430\u0414\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0419 \u0431\u0082\u0430\u0415\u0430\u041f\u0430\u0415\u0431\u0080\u0431\u008c {1}%.
# ICQ Transport
gateway.icq.shortservice=ICQ
gateway.icq.service=ICQ
gateway.icq.name=ICQ \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.icq.username=UIN/ICQ#
gateway.icq.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.icq.registration=\u0430\u0092\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 \u0430\u041d\u0430\u041e\u0430\u041c\u0430\u0415\u0431\u0080 ICQ# (UIN) \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c.
# MSN Transport
gateway.msn.shortservice=MSN
gateway.msn.service=MSN Messenger
gateway.msn.name=MSN \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.msn.username=\u0430\u0090\u0430\u0414\u0431\u0080\u0430\u0415\u0431\u0081 E-Mail
gateway.msn.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.msn.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410 \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 MSN Passport e-mail \u0430\u0410\u0430\u0414\u0431\u0080\u0430\u0415\u0431\u0081 \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c.
gateway.msn.passwordincorrect=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c, \u0430\u041a\u0430\u041e\u0431\u0082\u0430\u041e\u0431\u0080\u0431\u008b\u0430\u0419 \u0430\u0412\u0431\u008b \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041b\u0430\u0418 \u0430\u041d\u0430\u0415\u0430\u041a\u0430\u041e\u0431\u0080\u0431\u0080\u0430\u0415\u0430\u041a\u0431\u0082\u0430\u0415\u0430\u041d. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0431\u0083\u0430\u0419\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u008c \u0431\u0081 \u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0418\u0430\u041b\u0431\u008c\u0430\u041d\u0431\u008b\u0430\u041c \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0430\u0415\u0430\u041c.
gateway.msn.sendmsgfailed=\u0430\u009d\u0430\u0415 \u0430\u0412\u0430\u041e\u0430\u0417\u0430\u041c\u0430\u041e\u0430\u0416\u0430\u041d\u0430\u041e \u0430\u041e\u0431\u0082\u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c MSN \u0431\u0081\u0430\u041e\u0430\u041e\u0430\u0411\u0431\u0089\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0415. \u0430\u009f\u0431\u0080\u0430\u0418\u0431\u0087\u0430\u0418\u0430\u041d\u0430\u0410:
gateway.msn.illegalaccount=\u0430\u0092\u0431\u008b \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041b\u0430\u0418\u0431\u0081\u0431\u008c \u0431\u0087\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0417 MSN \u0431\u0082\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082 \u0431\u0081 \u0430\u041d\u0430\u0415\u0430\u041a\u0430\u041e\u0431\u0080\u0431\u0080\u0430\u0415\u0430\u041a\u0431\u0082\u0430\u041d\u0431\u008b\u0430\u041c \u0430\u041b\u0430\u041e\u0430\u0413\u0430\u0418\u0430\u041d\u0430\u041e\u0430\u041c.\n\u0430\u009b\u0430\u041e\u0430\u0413\u0430\u0418\u0430\u041d \u0430\u0414\u0430\u041e\u0430\u041b\u0430\u0416\u0430\u0415\u0430\u041d \u0430\u0412\u0431\u008b\u0430\u0413\u0430\u041b\u0431\u008f\u0430\u0414\u0430\u0415\u0431\u0082\u0431\u008c \u0430\u041a\u0430\u0410\u0430\u041a email \u0430\u0410\u0430\u0414\u0431\u0080\u0430\u0415\u0431\u0081.\n\u0430\u0092\u0431\u008b \u0430\u0416\u0430\u0415 \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d\u0431\u008b \u0430\u041a\u0430\u0410\u0430\u041a:
gateway.msn.disconnect=\u0430\u0092\u0431\u008b \u0430\u0411\u0431\u008b\u0430\u041b\u0430\u0418 \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0431\u008e\u0431\u0087\u0430\u0415\u0430\u041d\u0431\u008b \u0430\u041e\u0431\u0082 MSN \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0430\u0410.
gateway.msn.wink=\u0430\u0092\u0431\u008b \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0418\u0430\u041b\u0430\u0418 MSN wink.
gateway.msn.nudge=\u0430\u0092\u0431\u008b \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0418\u0430\u041b\u0430\u0418 MSN nudge.
gateway.msn.otherloggedin=\u0430\u0092\u0431\u008b \u0430\u0411\u0431\u008b\u0430\u041b\u0430\u0418 \u0430\u041e\u0431\u0082\u0431\u0081\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0430\u0415\u0430\u041d\u0431\u008b \u0430\u041e\u0431\u0082 MSN, \u0430\u041f\u0430\u041e\u0431\u0082\u0430\u041e\u0430\u041c\u0431\u0083 \u0431\u0087\u0431\u0082\u0430\u041e \u0430\u041a\u0431\u0082\u0430\u041e-\u0431\u0082\u0430\u041e \u0431\u0081 \u0430\u0412\u0430\u0410\u0431\u0088\u0430\u0418\u0430\u041c \u0430\u041b\u0430\u041e\u0430\u0413\u0430\u0418\u0430\u041d\u0430\u041e\u0430\u041c \u0431\u0081\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0430\u0418\u0430\u041b\u0431\u0081\u0431\u008f \u0430\u0415\u0431\u0089\u0430\u0415 \u0431\u0080\u0430\u0410\u0430\u0417 \u0430\u0418\u0430\u0417 \u0430\u0414\u0431\u0080\u0431\u0083\u0430\u0413\u0430\u041e\u0430\u0413\u0430\u041e \u0430\u041c\u0430\u0415\u0431\u0081\u0431\u0082\u0430\u0410.
# Yahoo Transport
gateway.yahoo.shortservice=Yahoo
gateway.yahoo.service=Yahoo! Messenger
gateway.yahoo.name=Yahoo! \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.yahoo.username=Yahoo! ID
gateway.yahoo.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.yahoo.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 Yahoo! ID \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c.
gateway.yahoo.error=\u0430\u009e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410 \u0430\u0418\u0430\u0417 Yahoo:
gateway.yahoo.mail=\u0430\u0403 \u0430\u0412\u0430\u0410\u0431\u0081 {0} \u0431\u0081\u0430\u041e\u0430\u041e\u0430\u0411\u0431\u0089\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0419 \u0430\u0412 \u0430\u0412\u0430\u0410\u0431\u0088\u0430\u0415\u0430\u0419 Yahoo! \u0430\u041f\u0430\u041e\u0431\u0087\u0431\u0082\u0430\u0415.
gateway.yahoo.loginrefused=\u0430\u009e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410 \u0430\u0412\u0431\u0085\u0430\u041e\u0430\u0414\u0430\u0410 \u0430\u0412 Yahoo! messenger. (\u0430\u041b\u0430\u041e\u0430\u0413\u0430\u0418\u0430\u041d \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d)
gateway.yahoo.unknownuser=Yahoo! \u0430\u041d\u0430\u0415 \u0431\u0080\u0430\u0410\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u0417\u0430\u041d\u0430\u0410\u0430\u041b \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f, \u0431\u0081 \u0430\u041a\u0430\u041e\u0431\u0082\u0430\u041e\u0431\u0080\u0431\u008b\u0430\u041c \u0430\u0412\u0431\u008b \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041b\u0430\u0418\u0431\u0081\u0431\u008c. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0417\u0430\u0410\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0431\u0083\u0430\u0419\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u008c \u0431\u0081 \u0430\u041a\u0430\u041e\u0431\u0080\u0431\u0080\u0430\u0415\u0430\u041a\u0431\u0082\u0430\u041d\u0431\u008b\u0430\u041c \u0430\u0418\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0415\u0430\u041c.
gateway.yahoo.badpassword=\u0430\u009b\u0430\u041e\u0430\u0413\u0430\u0418\u0430\u041d \u0430\u041e\u0431\u0082\u0430\u041a\u0430\u041b\u0430\u041e\u0430\u041d\u0430\u0415\u0430\u041d Yahoo!, \u0430\u0412\u0430\u041e\u0430\u0417\u0430\u041c\u0430\u041e\u0430\u0416\u0430\u041d\u0430\u041e \u0430\u041f\u0430\u041e\u0431\u0082\u0430\u041e\u0430\u041c\u0431\u0083 \u0431\u0087\u0431\u0082\u0430\u041e \u0430\u041d\u0430\u0415\u0430\u041a\u0430\u041e\u0431\u0080\u0431\u0080\u0430\u0415\u0430\u041a\u0431\u0082\u0430\u041d\u0431\u008b\u0430\u0419 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0431\u0083\u0430\u0419\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u008c \u0431\u0081 \u0430\u041d\u0430\u041e\u0431\u0080\u0430\u041c\u0430\u0410\u0430\u041b\u0431\u008c\u0430\u041d\u0431\u008b\u0430\u041c \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0430\u0415\u0430\u041c.
gateway.yahoo.accountlocked=\u0430\u0094\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f \u0430\u0417\u0430\u0410\u0430\u041a\u0431\u0080\u0431\u008b\u0431\u0082 \u0430\u0412 \u0430\u0412\u0430\u0410\u0431\u0088 Yahoo! \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082.
gateway.yahoo.accountlockedwithurl=\u0430\u0094\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f \u0430\u0417\u0430\u0410\u0430\u041a\u0431\u0080\u0431\u008b\u0431\u0082 \u0430\u0412 \u0430\u0412\u0430\u0410\u0431\u0088 Yahoo! \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410 \u0430\u0417\u0430\u0410\u0430\u0419\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0431\u0081\u0431\u008e\u0430\u0414\u0430\u0410: {0}
gateway.yahoo.unknownerror=\u0430\u009e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410 \u0430\u0412\u0431\u0085\u0430\u041e\u0430\u0414\u0430\u0410 \u0430\u0412 Yahoo! messenger \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082. (\u0430\u041d\u0430\u0415\u0430\u0418\u0430\u0417\u0430\u0412\u0430\u0415\u0431\u0081\u0431\u0082\u0430\u041d\u0430\u0410\u0431\u008f \u0430\u041e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410)
# IRC Transport
gateway.irc.shortservice=IRC
gateway.irc.service=IRC
gateway.irc.name=IRC \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.irc.username=\u0430\u0098\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f
gateway.irc.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.irc.nickname=\u0430\u009f\u0431\u0081\u0430\u0415\u0430\u0412\u0430\u0414\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c
gateway.irc.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088\u0430\u0418 IRC \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f, \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c, \u0430\u0418 \u0430\u041f\u0431\u0081\u0430\u0415\u0430\u0412\u0430\u0414\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c. \u0430\u009f\u0431\u0081\u0430\u0415\u0430\u0412\u0430\u0414\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c \u0430\u0418\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0431\u0083\u0430\u0415\u0431\u0082\u0431\u0081\u0431\u008f \u0430\u0414\u0430\u041b\u0431\u008f \u0430\u041e\u0430\u0411\u0431\u0089\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f, \u0430\u0412 \u0431\u0082\u0430\u041e \u0430\u0412\u0431\u0080\u0430\u0415\u0430\u041c\u0431\u008f \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c \u0430\u0418\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0431\u0083\u0431\u008e\u0431\u0082\u0431\u0081\u0431\u008f \u0430\u0414\u0430\u041b\u0431\u008f \u0430\u0410\u0430\u0412\u0431\u0082\u0430\u041e\u0431\u0080\u0430\u0418\u0430\u0417\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418. \u0430\u0095\u0431\u0081\u0430\u041b\u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c \u0430\u041d\u0430\u0415 \u0431\u0082\u0431\u0080\u0430\u0415\u0430\u0411\u0431\u0083\u0430\u0415\u0431\u0082\u0431\u0081\u0431\u008f, \u0430\u041e\u0431\u0081\u0431\u0082\u0430\u0410\u0430\u0412\u0431\u008c\u0431\u0082\u0430\u0415 \u0430\u0415\u0430\u0413\u0430\u041e \u0430\u041f\u0431\u0083\u0431\u0081\u0431\u0082\u0431\u008b\u0430\u041c.
gateway.irc.away=\u0430\u009e\u0431\u0082\u0430\u041e\u0431\u0088\u0430\u0415\u0430\u041b
gateway.irc.extendedaway=\u0430\u009e\u0431\u0082\u0431\u0081\u0431\u0083\u0431\u0082\u0431\u0081\u0431\u0082\u0430\u0412\u0431\u0083\u0430\u0415\u0431\u0082 \u0430\u0414\u0430\u0410\u0430\u0412\u0430\u041d\u0430\u041e
gateway.irc.donotdisturb=\u0430\u009d\u0430\u0415 \u0430\u0411\u0430\u0415\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041a\u0430\u041e\u0430\u0418\u0431\u0082\u0431\u008c
gateway.irc.errorreceived=\u0430\u009f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0415\u0430\u041d\u0430\u0410 \u0430\u041e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410 IRC:
gateway.irc.errorreceivedwithcode=\u0430\u009f\u0430\u041e\u0430\u041b\u0431\u0083\u0431\u0087\u0430\u0415\u0430\u041d\u0430\u0410 \u0430\u041e\u0431\u0088\u0430\u0418\u0430\u0411\u0430\u041a\u0430\u0410 IRC (code {0}):
# XMPP Transport
gateway.xmpp.shortservice=XMPP
gateway.xmpp.service=XMPP
gateway.xmpp.name=XMPP \u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.xmpp.username=JID
gateway.xmpp.password=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.xmpp.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 XMPP JID \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c, \u0431\u0082\u0430\u0410\u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u041e\u0430\u041d\u0430\u0418 \u0430\u0418\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0431\u0083\u0431\u008e\u0431\u0082\u0431\u0081\u0431\u008f XMPP \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u041e\u0430\u041c \u0431\u0083\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041d\u0430\u041d\u0431\u008b\u0430\u041c \u0430\u0412 \u0431\u0082\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082\u0430\u0415.
# Google Talk Transport
gateway.gtalk.shortservice=GTalk
gateway.gtalk.service=Google Talk
gateway.gtalk.name=Google Talk \u0431\u0082\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.gtalk.username=\u0430\u0090\u0430\u0414\u0431\u0080\u0430\u0415\u0431\u0081
gateway.gtalk.registration=\u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u0412\u0430\u0415\u0430\u0414\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u0412\u0430\u0410\u0431\u0088 e-mail \u0430\u0410\u0430\u0414\u0431\u0080\u0430\u0415\u0431\u0081 \u0430\u0418 \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c \u0430\u0418\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0431\u0083\u0431\u008e\u0431\u0089\u0430\u0418\u0430\u0415\u0431\u0081\u0431\u008f \u0430\u0412 GMail \u0430\u0418 GTalk.
# Web Interface (Settings)
gateway.web.settings.instructions=\u0430\u0092\u0431\u008b\u0430\u0411\u0430\u0415\u0431\u0080\u0430\u0418\u0431\u0082\u0430\u0415,\u0430\u041a\u0430\u0410\u0430\u041a\u0430\u041e\u0430\u0419 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u0411\u0431\u0083\u0430\u0414\u0430\u0415\u0431\u0082 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0415\u0430\u041d, \u0430\u041a\u0430\u0410\u0430\u041a\u0430\u0418\u0430\u0415 \u0430\u0412\u0430\u041e\u0430\u0417\u0430\u041c\u0430\u041e\u0430\u0416\u0430\u041d\u0430\u041e\u0431\u0081\u0431\u0082\u0430\u0418 \u0430\u041e\u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0430\u0415\u0430\u041b\u0430\u0415\u0430\u041d\u0431\u008b, \u0430\u0418 \u0430\u041a\u0431\u0082\u0430\u041e \u0430\u0418\u0430\u041c\u0430\u0415\u0430\u0415\u0431\u0082 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f \u0430\u041a \u0430\u041a\u0430\u0410\u0430\u041a\u0430\u041e\u0430\u041c\u0431\u0083 \u0431\u0082\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082\u0430\u041d\u0430\u041e\u0430\u041c\u0431\u0083 \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0431\u0083. \u0430\u0092\u0431\u008b\u0430\u0411\u0430\u041e\u0431\u0080 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u0410 \u0430\u0412\u0430\u041a\u0430\u041b\u0431\u008e\u0431\u0087\u0430\u0410\u0430\u0415\u0431\u0082 \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081.
gateway.web.settings.tests=\u0430\u0402\u0430\u0415\u0431\u0081\u0431\u0082\u0431\u008b
gateway.web.settings.options=\u0430\u009f\u0430\u0410\u0431\u0080\u0430\u0410\u0430\u041c\u0430\u0415\u0431\u0082\u0431\u0080\u0431\u008b
gateway.web.settings.permissions=\u0430\u009f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0410 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0410
gateway.web.settings.connecttohost=\u0430\u0401\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c\u0431\u0081\u0431\u008f \u0431\u0081 \u0431\u0085\u0430\u041e\u0431\u0081\u0431\u0082\u0430\u041e\u0430\u041c
gateway.web.settings.connecttoport=\u0430\u0401\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c\u0431\u0081\u0431\u008f \u0431\u0081 \u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082\u0430\u041e\u0430\u041c
gateway.web.settings.testconnection=\u0430\u009f\u0431\u0080\u0430\u041e\u0431\u0082\u0430\u0415\u0431\u0081\u0431\u0082\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0431\u008c \u0431\u0081\u0430\u041e\u0430\u0415\u0430\u0414\u0430\u0418\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0418\u0430\u0415
gateway.web.settings.saveoptions=\u0430\u0401\u0430\u041e\u0431\u0085\u0431\u0080\u0430\u0410\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u041f\u0430\u0410\u0431\u0080\u0430\u0410\u0430\u041c\u0430\u0415\u0431\u0082\u0431\u0080\u0431\u008b
gateway.web.settings.cancelchanges=\u0430\u009e\u0431\u0082\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u0418\u0430\u0417\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f
gateway.web.settings.registernone=\u0430\u0402\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u041a\u0430\u041e \u0431\u0080\u0431\u0083\u0431\u0087\u0430\u041d\u0430\u0410\u0431\u008f \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f (\u0431\u0081\u0430\u041c\u0430\u041e\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0082\u0430\u0415 \u0431\u0080\u0430\u0410\u0430\u0417\u0430\u0414\u0430\u0415\u0430\u041b \u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418 \u0430\u0414\u0430\u041b\u0431\u008f \u0431\u0083\u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f)
gateway.web.settings.registersome=\u0430\u00ad\u0431\u0082\u0430\u0418 \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0430\u0418 \u0430\u0418/\u0430\u0418\u0430\u041b\u0430\u0418 \u0430\u0413\u0431\u0080\u0431\u0083\u0430\u041f\u0430\u041f\u0431\u008b \u0430\u041c\u0430\u041e\u0430\u0413\u0431\u0083\u0431\u0082 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0431\u008c\u0431\u0081\u0431\u008f
gateway.web.settings.registerall=\u0430\u0092\u0431\u0081\u0430\u0415 \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0430\u0418 \u0430\u041c\u0430\u041e\u0430\u0413\u0431\u0083\u0431\u0082 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0431\u008c\u0431\u0081\u0431\u008f
gateway.web.settings.users=\u0430\u009f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0430\u0418
gateway.web.settings.groups=\u0430\u0093\u0431\u0080\u0431\u0083\u0430\u041f\u0430\u041f\u0431\u008b
gateway.web.settings.savepermissions=\u0430\u0401\u0430\u041e\u0431\u0085\u0431\u0080\u0430\u0410\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0410 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0410
gateway.web.settings.title=\u0430\u009d\u0430\u0410\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u041e\u0430\u0419\u0430\u041a\u0430\u0418 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u0410
gateway.web.settings.settingssaved=\u0430\u009d\u0430\u0410\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u041e\u0430\u0419\u0430\u041a\u0430\u0418 \u0431\u0081\u0430\u041e\u0431\u0085\u0431\u0080\u0430\u0410\u0430\u041d\u0430\u0415\u0430\u041d\u0431\u008b
gateway.web.settings.cancelledchanges=\u0430\u0098\u0430\u0417\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u008f \u0430\u041e\u0431\u0082\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0415\u0430\u041d\u0431\u008b
gateway.web.settings.success=\u0430\u0403\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0088\u0430\u041d\u0430\u041e
gateway.web.settings.failed=\u0430\u009d\u0430\u0415 \u0431\u0083\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0088\u0430\u041d\u0430\u041e
gateway.web.settings.permissionssaved=\u0430\u009f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0410 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0410 \u0431\u0081\u0430\u041e\u0431\u0085\u0431\u0080\u0430\u0410\u0430\u041d\u0430\u0415\u0430\u041d\u0431\u008b
gateway.web.settings.host=\u0430\u0405\u0430\u041e\u0431\u0081\u0431\u0082
gateway.web.settings.port=\u0430\u009f\u0430\u041e\u0431\u0080\u0431\u0082
gateway.web.settings.encoding=\u0430\u009a\u0430\u041e\u0430\u0414\u0430\u0418\u0431\u0080\u0430\u041e\u0430\u0412\u0430\u041a\u0430\u0410
gateway.web.settings.unstable.title=\u0430\u00ad\u0430\u041a\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0418\u0430\u041c\u0430\u0415\u0430\u041d\u0431\u0082\u0430\u0410\u0430\u041b\u0431\u008c\u0430\u041d\u0431\u008b\u0430\u0419 \u0430\u0408\u0430\u041b\u0431\u008e\u0430\u0417
gateway.web.settings.unstable.notice=\u0430\u0401\u0430\u041b\u0430\u0415\u0430\u0414\u0431\u0083\u0431\u008e\u0431\u0089\u0430\u0418\u0430\u0415 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0431\u008b \u0431\u008d\u0430\u041a\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0418\u0430\u041c\u0430\u0415\u0430\u041d\u0431\u0082\u0430\u0410\u0430\u041b\u0431\u008c\u0430\u041d\u0431\u008b\u0430\u0415 \u0430\u0418 \u0430\u041d\u0430\u0415 \u0431\u0080\u0430\u0415\u0430\u041a\u0430\u041e\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0414\u0431\u0083\u0431\u008e\u0431\u0082\u0431\u0081\u0431\u008f \u0430\u041a \u0430\u0418\u0431\u0081\u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0430\u041d\u0430\u0418\u0431\u008e. \u0430\u009e\u0430\u041d\u0430\u0418 \u0430\u041f\u0431\u0080\u0430\u0415\u0430\u0414\u0430\u041d\u0430\u0410\u0430\u0417\u0430\u041d\u0430\u0410\u0431\u0087\u0430\u0415\u0430\u041d\u0431\u008b \u0430\u0414\u0430\u041b\u0431\u008f \u0431\u0082\u0430\u0415\u0431\u0085, \u0430\u041a\u0430\u041e\u0430\u041c\u0431\u0083 \u0430\u0418\u0430\u041d\u0431\u0082\u0430\u0415\u0431\u0080\u0430\u0415\u0431\u0081\u0430\u041d\u0430\u041e \u0430\u041f\u0430\u041e\u0430\u041f\u0431\u0080\u0430\u041e\u0430\u0411\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0431\u008c \u0430\u041d\u0430\u0415\u0431\u0081\u0431\u0082\u0430\u0410\u0430\u0411\u0430\u0418\u0430\u041b\u0431\u008c\u0430\u041d\u0431\u008b\u0430\u0415 \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0431\u008b \u0430\u0418 \u0430\u041a\u0431\u0082\u0430\u041e \u0430\u041f\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c\u0430\u0410\u0430\u0415\u0431\u0082, \u0431\u0087\u0431\u0082\u0430\u041e \u0430\u041e\u0430\u041d\u0430\u0418 \u0430\u041c\u0430\u041e\u0430\u0413\u0431\u0083\u0431\u0082 \u0431\u0080\u0430\u0410\u0430\u0411\u0430\u041e\u0431\u0082\u0430\u0410\u0431\u0082\u0431\u008c \u0430\u041d\u0430\u0415\u0430\u041a\u0430\u041e\u0431\u0080\u0431\u0080\u0430\u0415\u0430\u041a\u0431\u0082\u0430\u041d\u0430\u041e.
# Web Interface (Registrations)
gateway.web.registrations.instructions=\u0430\u009d\u0430\u0418\u0430\u0416\u0430\u0415 \u0431\u0081\u0430\u041f\u0430\u0418\u0431\u0081\u0430\u041e\u0430\u041a \u0430\u0412\u0431\u0081\u0430\u0415\u0431\u0085 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u041e\u0430\u0412\u0431\u008b\u0431\u0085 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0419. \u0430\u0094\u0430\u041b\u0431\u008f \u0431\u0084\u0430\u0418\u0430\u041b\u0431\u008c\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418 \u0430\u0410\u0430\u041a\u0431\u0082\u0430\u0418\u0430\u0412\u0430\u041d\u0431\u008b\u0431\u0085 \u0431\u0081\u0430\u0415\u0431\u0081\u0431\u0081\u0430\u0418\u0430\u0419 \u0430\u0418/\u0430\u0418\u0430\u041b\u0430\u0418 \u0430\u041a\u0430\u041e\u0430\u041d\u0430\u041a\u0431\u0080\u0430\u0415\u0431\u0082\u0430\u041d\u0431\u008b\u0431\u0085 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u041e\u0430\u0412, \u0430\u0412\u0431\u008b\u0430\u0411\u0430\u0415\u0431\u0080\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u041e\u0430\u041f\u0431\u0086\u0430\u0418\u0430\u0418 \u0430\u041d\u0430\u0418\u0430\u0416\u0430\u0415 \u0430\u0418 \u0430\u041d\u0430\u0410\u0430\u0416\u0430\u041c\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u041a\u0430\u041d\u0430\u041e\u0430\u041f\u0430\u041a\u0431\u0083 \u0430\u041e\u0430\u0411\u0430\u041d\u0430\u041e\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c.
gateway.web.registrations.addnewreg=\u0430\u0094\u0430\u041e\u0430\u0411\u0430\u0410\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u041d\u0430\u041e\u0430\u0412\u0431\u0083\u0431\u008e \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008e
gateway.web.registrations.cancelnewreg=\u0430\u009e\u0431\u0082\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c \u0430\u0412\u0430\u0412\u0430\u041e\u0430\u0414 \u0430\u041d\u0430\u041e\u0430\u0412\u0430\u041e\u0430\u0419 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0082\u0431\u0081\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418
gateway.web.registrations.username=\u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f
gateway.web.registrations.password=\u0430\u041f\u0430\u0410\u0431\u0080\u0430\u041e\u0430\u041b\u0431\u008c
gateway.web.registrations.nickname=\u0430\u041f\u0431\u0081\u0430\u0415\u0430\u0412\u0430\u0414\u0430\u041e\u0430\u041d\u0430\u0418\u0430\u041c
gateway.web.registrations.jid=user (JID)
gateway.web.registrations.gateway=\u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417
gateway.web.registrations.signedon=\u0430\u0090\u0430\u041a\u0431\u0082\u0430\u0418\u0430\u0412\u0430\u041d\u0431\u008b\u0430\u0415 \u0431\u0081\u0430\u0415\u0431\u0081\u0431\u0081\u0430\u0418\u0430\u0418
gateway.web.registrations.update=\u0430\u009e\u0430\u0411\u0430\u041d\u0430\u041e\u0430\u0412\u0430\u0418\u0431\u0082\u0431\u008c
gateway.web.registrations.next=\u0430\u0401\u0430\u041b\u0430\u0415\u0430\u0414.
gateway.web.registrations.prev=\u0430\u009f\u0431\u0080\u0430\u0415\u0430\u0414.
gateway.web.registrations.remove=\u0430\u0403\u0430\u0414\u0430\u0410\u0430\u041b\u0430\u0418\u0431\u0082\u0431\u008c
gateway.web.registrations.edit=\u0430\u0098\u0430\u0417\u0430\u041c\u0430\u0415\u0430\u041d\u0430\u0418\u0431\u0082\u0431\u008c
gateway.web.registrations.lastlogin=\u0430\u009f\u0430\u041e\u0431\u0081\u0430\u041b\u0430\u0415\u0430\u0414\u0430\u041d\u0430\u0418\u0430\u0419 \u0430\u0412\u0431\u0085\u0430\u041e\u0430\u0414
gateway.web.registrations.serviceusername=\u0430\u0401\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081/\u0430\u0098\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f
gateway.web.registrations.user=\u0430\u009f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008c
gateway.web.registrations.confirmdelete=\u0430\u0092\u0431\u008b \u0431\u0083\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u041d\u0431\u008b, \u0431\u0087\u0431\u0082\u0430\u041e \u0431\u0085\u0430\u041e\u0431\u0082\u0430\u0418\u0431\u0082\u0430\u0415 \u0431\u0083\u0430\u0414\u0430\u0410\u0430\u041b\u0430\u0418\u0431\u0082\u0431\u008c \u0431\u008d\u0431\u0082\u0431\u0083 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008e?
gateway.web.registrations.registrations=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418
gateway.web.registrations.title=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0430\u0418 \u0430\u0412 \u0431\u0088\u0430\u041b\u0431\u008e\u0430\u0417\u0430\u0410\u0431\u0085
gateway.web.registrations.xmppnotfound=\u0430\u009d\u0430\u0415 \u0430\u041c\u0430\u041e\u0430\u0413\u0431\u0083 \u0430\u041d\u0430\u0410\u0430\u0419\u0431\u0082\u0430\u0418 \u0431\u0081\u0431\u0087\u0430\u0415\u0431\u0082 XMPP \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f.
gateway.web.registrations.regnotfound=\u0430\u009d\u0430\u0415 \u0430\u041c\u0430\u041e\u0430\u0413\u0431\u0083 \u0430\u041d\u0430\u0410\u0430\u0419\u0431\u0082\u0430\u0418 \u0431\u0080\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008e.
gateway.web.registrations.notenabled=\u0430\u0402\u0431\u0080\u0430\u0410\u0430\u041d\u0431\u0081\u0430\u041f\u0430\u041e\u0431\u0080\u0431\u0082 \u0430\u041d\u0430\u0415 \u0430\u0414\u0430\u041e\u0431\u0081\u0431\u0082\u0431\u0083\u0430\u041f\u0430\u0415\u0430\u041d. \u0430\u009f\u0430\u041e\u0430\u0416\u0430\u0410\u0430\u041b\u0431\u0083\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0410, \u0430\u0412\u0430\u041a\u0430\u041b\u0431\u008e\u0431\u0087\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0415\u0430\u0414 \u0431\u0082\u0430\u0415\u0430\u041c, \u0430\u041a\u0430\u0410\u0430\u041a \u0430\u0412\u0431\u008b\u0430\u041f\u0430\u041e\u0430\u041b\u0430\u041d\u0430\u0418\u0431\u0082\u0430\u0415 \u0430\u041e\u0430\u041f\u0430\u0415\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008e.
gateway.web.registrations.illegaldomain=\u0430\u0094\u0430\u041e\u0430\u041c\u0430\u0415\u0430\u041d XMPP \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0430\u0410\u0431\u0082\u0430\u0415\u0430\u041b\u0431\u008f \u0430\u041d\u0430\u0415 \u0430\u041d\u0430\u0410 \u0431\u008d\u0431\u0082\u0430\u041e\u0430\u041c \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0415\u0431\u0080\u0430\u0415.
gateway.web.registrations.invaliduser=\u0430\u009d\u0430\u0415\u0430\u041f\u0431\u0080\u0430\u0410\u0430\u0412\u0430\u0418\u0430\u041b\u0431\u008c\u0430\u041d\u0430\u041e\u0430\u0415 \u0430\u0418\u0430\u041c\u0431\u008f \u0430\u041f\u0430\u041e\u0430\u041b\u0431\u008c\u0430\u0417\u0430\u041e\u0430\u0412\u0431\u0082\u0430\u0410\u0430\u0415\u0430\u041b\u0431\u008f \u0431\u0083\u0430\u041a\u0430\u0410\u0430\u0417\u0430\u0410\u0430\u041d\u0430\u041e \u0430\u0414\u0430\u041b\u0431\u008f \u0430\u0414\u0430\u0415\u0430\u0419\u0431\u0081\u0431\u0082\u0430\u0412\u0431\u0083\u0431\u008e\u0431\u0089\u0430\u0415\u0430\u0413\u0430\u041e \u0431\u0081\u0430\u0415\u0431\u0080\u0430\u0412\u0430\u0418\u0431\u0081\u0430\u0410.
gateway.web.registrations.deletesuccess=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0431\u0083\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0088\u0430\u041d\u0430\u041e \u0431\u0083\u0430\u0414\u0430\u0410\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0410.
gateway.web.registrations.updatesuccess=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0431\u0083\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0088\u0430\u041d\u0430\u041e \u0430\u041e\u0430\u0411\u0430\u041d\u0430\u041e\u0430\u0412\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0410.
gateway.web.registrations.addsuccess=\u0430\u00a0\u0430\u0415\u0430\u0413\u0430\u0418\u0431\u0081\u0431\u0082\u0431\u0080\u0430\u0410\u0431\u0086\u0430\u0418\u0431\u008f \u0431\u0083\u0431\u0081\u0430\u041f\u0430\u0415\u0431\u0088\u0430\u041d\u0430\u041e \u0430\u0414\u0430\u041e\u0430\u0411\u0430\u0410\u0430\u0412\u0430\u041b\u0430\u0415\u0430\u041d\u0430\u0410.
gateway.web.registrations.never=never
gateway.web.registrations.page=Page
gateway.web.registrations.perpage=per page
\ No newline at end of file
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.QName;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.*;
import org.jivesoftware.openfire.user.UserAlreadyExistsException;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentManager;
import org.xmpp.forms.DataForm;
import org.xmpp.forms.FormField;
import org.xmpp.packet.*;
import org.xmpp.packet.PacketError.Condition;
import java.util.*;
/**
* Base class of all transport implementations.
*
* Handles all transport non-specific tasks and provides the glue that holds
* together server interactions and the legacy service. Does the bulk of
* the XMPP related work. Also note that this represents the transport
* itself, not an individual session with the transport.
*
* @author Daniel Henninger
*/
public abstract class BaseTransport implements Component, RosterEventListener {
/**
* Create a new BaseTransport instance.
*/
public BaseTransport() {
// We've got nothing to do here.
}
/**
* Set up the transport instance.
*
* @param type Type of the transport.
* @param description Description of the transport (for Disco).
*/
public void setup(TransportType type, String description) {
this.description = description;
this.transportType = type;
permissionManager = new PermissionManager(transportType);
}
/**
* Handles initialization of the transport.
*/
public void initialize(JID jid, ComponentManager componentManager) {
this.jid = jid;
this.componentManager = componentManager;
rosterManager = XMPPServer.getInstance().getRosterManager();
sessionManager.startThreadManager(jid);
}
/**
* Manages all active sessions.
* @see org.jivesoftware.openfire.gateway.TransportSessionManager
*/
public final TransportSessionManager sessionManager = new TransportSessionManager(this);
/**
* Manages registration information.
* @see org.jivesoftware.openfire.gateway.RegistrationManager
*/
public final RegistrationManager registrationManager = new RegistrationManager();
/**
* Manages permission information.
* @see org.jivesoftware.openfire.gateway.PermissionManager
*/
public PermissionManager permissionManager = null;
/**
* JID of the transport in question.
*/
public JID jid = null;
/**
* Description of the transport in question.
*/
public String description = null;
/**
* Component Manager associated with transport.
*/
public ComponentManager componentManager = null;
/**
* Manager component for user rosters.
*/
public RosterManager rosterManager;
/**
* Type of the transport in question.
* @see org.jivesoftware.openfire.gateway.TransportType
*/
public TransportType transportType = null;
private final String DISCO_INFO = "http://jabber.org/protocol/disco#info";
private final String DISCO_ITEMS = "http://jabber.org/protocol/disco#items";
private final String IQ_GATEWAY = "jabber:iq:gateway";
private final String IQ_GATEWAY_REGISTER = "jabber:iq:gateway:register";
private final String IQ_REGISTER = "jabber:iq:register";
private final String IQ_REGISTERED = "jabber:iq:registered";
private final String IQ_VERSION = "jabber:iq:version";
private final String CHATSTATES = "http://jabber.org/protocol/chatstates";
private final String XEVENT = "jabber:x:event";
/**
* Handles all incoming XMPP stanzas, passing them to individual
* packet type handlers.
*
* @param packet The packet to be processed.
*/
public void processPacket(Packet packet) {
try {
List<Packet> reply = new ArrayList<Packet>();
if (packet instanceof IQ) {
reply.addAll(processPacket((IQ)packet));
}
else if (packet instanceof Presence) {
reply.addAll(processPacket((Presence)packet));
}
else if (packet instanceof Message) {
reply.addAll(processPacket((Message)packet));
}
else {
Log.info("Received an unhandled packet: " + packet.toString());
}
if (reply.size() > 0) {
for (Packet p : reply) {
this.sendPacket(p);
}
}
}
catch (Exception e) {
Log.error("Error occured while processing packet:", e);
}
}
/**
* Handles all incoming message stanzas.
*
* @param packet The message packet to be processed.
* @return list of packets that will be sent back to the message sender.
*/
private List<Packet> processPacket(Message packet) {
Log.debug("Received message packet: "+packet.toXML());
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
JID to = packet.getTo();
try {
TransportSession session = sessionManager.getSession(from);
if (!session.isLoggedIn()) {
Message m = new Message();
m.setError(Condition.service_unavailable);
m.setTo(from);
m.setFrom(getJID());
m.setBody(LocaleUtils.getLocalizedString("gateway.base.notloggedin", "gateway", Arrays.asList(transportType.toString().toUpperCase())));
reply.add(m);
}
else if (to.getNode() == null) {
// Message to gateway itself. Throw away for now.
if (packet.getBody() != null) {
session.sendServerMessage(packet.getBody());
}
}
else {
if (packet.getBody() != null) {
session.sendMessage(to, packet.getBody());
}
else {
// Checking for XEP-0022 message events
Element eEvent = packet.getChildElement("x", XEVENT);
if (eEvent != null) {
if (eEvent.element("composing") != null) {
session.sendChatState(to, ChatStateType.composing);
}
else {
session.sendChatState(to, ChatStateType.paused);
}
}
else {
// Ok then, lets check for XEP-0085 chat states
if (packet.getChildElement("composing", CHATSTATES) != null) {
session.sendChatState(to, ChatStateType.composing);
}
else if (packet.getChildElement("active", CHATSTATES) != null) {
session.sendChatState(to, ChatStateType.active);
}
else if (packet.getChildElement("inactive", CHATSTATES) != null) {
session.sendChatState(to, ChatStateType.inactive);
}
else if (packet.getChildElement("paused", CHATSTATES) != null) {
session.sendChatState(to, ChatStateType.paused);
}
else if (packet.getChildElement("gone", CHATSTATES) != null) {
session.sendChatState(to, ChatStateType.gone);
}
}
}
}
}
catch (NotFoundException e) {
Log.debug("Unable to find session.");
Message m = new Message();
m.setError(Condition.service_unavailable);
m.setTo(from);
m.setFrom(getJID());
m.setBody(LocaleUtils.getLocalizedString("gateway.base.notloggedin", "gateway", Arrays.asList(transportType.toString().toUpperCase())));
reply.add(m);
}
return reply;
}
/**
* Handles all incoming presence stanzas.
*
* @param packet The presence packet to be processed.
* @return list of packets that will be sent back to the presence requester.
*/
private List<Packet> processPacket(Presence packet) {
Log.debug("Received presence packet: "+packet.toXML());
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
JID to = packet.getTo();
if (packet.getType() == Presence.Type.error) {
// We don't want to do anything with this. Ignore it.
return reply;
}
try {
if (to.getNode() == null) {
Collection<Registration> registrations = registrationManager.getRegistrations(from, this.transportType);
if (registrations.isEmpty()) {
// User is not registered with us.
Log.debug("Unable to find registration.");
return reply;
}
Registration registration = registrations.iterator().next();
// This packet is to the transport itself.
if (packet.getType() == null) {
// A user's resource has come online.
TransportSession session;
try {
session = sessionManager.getSession(from);
if (session.hasResource(from.getResource())) {
Log.debug("An existing resource has changed status: " + from);
if (session.getPriority(from.getResource()) != packet.getPriority()) {
session.updatePriority(from.getResource(), packet.getPriority());
}
if (session.isHighestPriority(from.getResource())) {
// Well, this could represent a status change.
session.updateStatus(getPresenceType(packet), packet.getStatus());
}
}
else {
Log.debug("A new resource has come online: " + from);
// This is a new resource, lets send them what we know.
session.addResource(from.getResource(), packet.getPriority());
// Tell the new resource what the state of their buddy list is.
session.resendContactStatuses(from);
// If this priority is the highest, treat it's status as golden
if (session.isHighestPriority(from.getResource())) {
session.updateStatus(getPresenceType(packet), packet.getStatus());
}
}
}
catch (NotFoundException e) {
Log.debug("A new session has come online: " + from);
session = this.registrationLoggedIn(registration, from, getPresenceType(packet), packet.getStatus(), packet.getPriority());
sessionManager.storeSession(from, session);
}
}
else if (packet.getType() == Presence.Type.unavailable) {
// A user's resource has gone offline.
TransportSession session;
try {
session = sessionManager.getSession(from);
if (session.getResourceCount() > 1) {
String resource = from.getResource();
// Just one of the resources, lets adjust accordingly.
if (session.isHighestPriority(resource)) {
Log.debug("A high priority resource (of multiple) has gone offline: " + from);
// Ooh, the highest resource went offline, drop to next highest.
session.removeResource(resource);
// Lets ask the next highest resource what it's presence is.
Presence p = new Presence(Presence.Type.probe);
p.setTo(session.getJIDWithHighestPriority());
p.setFrom(this.getJID());
sendPacket(p);
}
else {
Log.debug("A low priority resource (of multiple) has gone offline: " + from);
// Meh, lower priority, big whoop.
session.removeResource(resource);
}
}
else {
Log.debug("A final resource has gone offline: " + from);
// No more resources, byebye.
if (session.isLoggedIn()) {
this.registrationLoggedOut(session);
}
sessionManager.removeSession(from);
}
}
catch (NotFoundException e) {
Log.debug("Ignoring unavailable presence for inactive seession.");
}
}
else if (packet.getType() == Presence.Type.probe) {
// Client is asking for presence status.
TransportSession session;
try {
session = sessionManager.getSession(from);
if (session.isLoggedIn()) {
Presence p = new Presence();
p.setTo(from);
p.setFrom(to);
this.sendPacket(p);
}
}
catch (NotFoundException e) {
Log.debug("Ignoring probe presence for inactive session.");
}
}
else {
Log.debug("Ignoring this packet:" + packet.toString());
// Anything else we will ignore for now.
}
}
else {
// This packet is to a user at the transport.
try {
TransportSession session = sessionManager.getSession(from);
if (packet.getType() == Presence.Type.probe) {
// Presence probe, lets try to tell them.
session.retrieveContactStatus(to);
}
else {
// Anything else we will ignore for now.
}
}
catch (NotFoundException e) {
// Well we just don't care then.
}
}
}
catch (Exception e) {
Log.error("Exception while processing packet: ", e);
}
return reply;
}
/**
* Handles all incoming iq stanzas.
*
* @param packet The iq packet to be processed.
* @return list of packets that will be sent back to the IQ requester.
*/
private List<Packet> processPacket(IQ packet) {
Log.debug("Received iq packet: "+packet.toXML());
List<Packet> reply = new ArrayList<Packet>();
if (packet.getType() == IQ.Type.error) {
// Lets not start a loop. Ignore.
return reply;
}
String xmlns = null;
Element child = (packet).getChildElement();
if (child != null) {
xmlns = child.getNamespaceURI();
}
if (xmlns == null) {
// No namespace defined.
Log.debug("No XMLNS:" + packet.toString());
IQ error = IQ.createResultIQ(packet);
error.setError(Condition.bad_request);
reply.add(error);
return reply;
}
if (xmlns.equals(DISCO_INFO)) {
reply.addAll(handleDiscoInfo(packet));
}
else if (xmlns.equals(DISCO_ITEMS)) {
reply.addAll(handleDiscoItems(packet));
}
else if (xmlns.equals(IQ_GATEWAY)) {
reply.addAll(handleIQGateway(packet));
}
else if (xmlns.equals(IQ_REGISTER)) {
reply.addAll(handleIQRegister(packet));
}
else if (xmlns.equals(IQ_VERSION)) {
reply.addAll(handleIQVersion(packet));
}
else {
Log.debug("Unable to handle iq request: " + xmlns);
IQ error = IQ.createResultIQ(packet);
error.setError(Condition.service_unavailable);
reply.add(error);
}
return reply;
}
/**
* Handle service discovery info request.
*
* @param packet An IQ packet in the disco info namespace.
* @return A list of IQ packets to be returned to the user.
*/
private List<Packet> handleDiscoInfo(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
if (packet.getTo().getNode() == null) {
// Requested info from transport itself.
IQ result = IQ.createResultIQ(packet);
Element response = DocumentHelper.createElement(QName.get("query", DISCO_INFO));
response.addElement("identity")
.addAttribute("category", "gateway")
.addAttribute("type", this.transportType.toString())
.addAttribute("name", this.description);
response.addElement("feature")
.addAttribute("var", IQ_GATEWAY);
response.addElement("feature")
.addAttribute("var", IQ_REGISTER);
response.addElement("feature")
.addAttribute("var", IQ_VERSION);
Collection<Registration> registrations = registrationManager.getRegistrations(from, this.transportType);
if (!registrations.isEmpty()) {
response.addElement("feature")
.addAttribute("var", IQ_REGISTERED);
}
result.setChildElement(response);
reply.add(result);
}
return reply;
}
/**
* Handle service discovery items request.
*
* @param packet An IQ packet in the disco items namespace.
* @return A list of IQ packets to be returned to the user.
*/
private List<Packet> handleDiscoItems(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
IQ result = IQ.createResultIQ(packet);
reply.add(result);
return reply;
}
/**
* Handle gateway translation service request.
*
* @param packet An IQ packet in the iq gateway namespace.
* @return A list of IQ packets to be returned to the user.
*/
private List<Packet> handleIQGateway(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
if (packet.getType() == IQ.Type.get) {
IQ result = IQ.createResultIQ(packet);
Element query = DocumentHelper.createElement(QName.get("query", IQ_GATEWAY));
query.addElement("desc").addText(LocaleUtils.getLocalizedString("gateway.base.enterusername", "gateway", Arrays.asList(transportType.toString().toUpperCase())));
query.addElement("prompt");
result.setChildElement(query);
reply.add(result);
}
else if (packet.getType() == IQ.Type.set) {
IQ result = IQ.createResultIQ(packet);
String prompt = null;
Element promptEl = packet.getChildElement().element("prompt");
if (promptEl != null) {
prompt = promptEl.getTextTrim();
}
if (prompt == null) {
result.setError(Condition.bad_request);
}
else {
JID jid = this.convertIDToJID(prompt);
Element query = DocumentHelper.createElement(QName.get("query", IQ_GATEWAY));
// This is what Psi expects
query.addElement("prompt").addText(jid.toString());
// This is JEP complient
query.addElement("jid").addText(jid.toString());
result.setChildElement(query);
}
reply.add(result);
}
return reply;
}
/**
* Handle registration request.
*
* @param packet An IQ packet in the iq registration namespace.
* @return A list of IQ packets to be returned to the user.
*/
private List<Packet> handleIQRegister(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
JID from = packet.getFrom();
JID to = packet.getTo();
Element remove = packet.getChildElement().element("remove");
if (remove != null) {
// User wants to unregister. =(
// this.convinceNotToLeave() ... kidding.
IQ result = IQ.createResultIQ(packet);
if (packet.getChildElement().elements().size() != 1) {
result.setError(Condition.bad_request);
reply.add(result);
return reply;
}
// Tell the end user the transport went byebye.
Presence unavailable = new Presence(Presence.Type.unavailable);
unavailable.setTo(from);
unavailable.setFrom(to);
reply.add(unavailable);
try {
this.deleteRegistration(from);
}
catch (UserNotFoundException e) {
Log.error("Error cleaning up contact list of: " + from);
result.setError(Condition.registration_required);
}
reply.add(result);
}
else {
// User wants to register with the transport.
String username = null;
String password = null;
String nickname = null;
try {
DataForm form = new DataForm(packet.getChildElement().element("x"));
List<FormField> fields = form.getFields();
for (FormField field : fields) {
String var = field.getVariable();
if (var.equals("username")) {
username = field.getValues().get(0);
}
else if (var.equals("password")) {
password = field.getValues().get(0);
}
else if (var.equals("nick")) {
nickname = field.getValues().get(0);
}
}
}
catch (Exception e) {
// No with data form apparantly
}
if (packet.getType() == IQ.Type.set) {
Boolean registered = false;
Collection<Registration> registrations = registrationManager.getRegistrations(from, this.transportType);
if (registrations.iterator().hasNext()) {
registered = true;
}
if (!registered && !permissionManager.hasAccess(from)) {
// User does not have permission to register with transport.
// We want to allow them to change settings if they are already registered.
IQ result = IQ.createResultIQ(packet);
result.setError(Condition.forbidden);
reply.add(result);
Message em = new Message();
em.setType(Message.Type.error);
em.setTo(packet.getFrom());
em.setFrom(packet.getTo());
em.setBody(LocaleUtils.getLocalizedString("gateway.base.registrationdeniedbyacls", "gateway"));
reply.add(em);
return reply;
}
Element userEl = packet.getChildElement().element("username");
Element passEl = packet.getChildElement().element("password");
Element nickEl = packet.getChildElement().element("nick");
if (userEl != null) {
username = userEl.getTextTrim();
}
if (passEl != null) {
password = passEl.getTextTrim();
}
if (nickEl != null) {
nickname = nickEl.getTextTrim();
}
username = (username == null || username.equals("")) ? null : username;
password = (password == null || password.equals("")) ? null : password;
nickname = (nickname == null || nickname.equals("")) ? null : nickname;
if ( username == null
|| (isPasswordRequired() && password == null)
|| (isNicknameRequired() && nickname == null)) {
// Invalid information from stanza, lets yell.
IQ result = IQ.createResultIQ(packet);
result.setError(Condition.bad_request);
reply.add(result);
}
else {
boolean rosterlessMode = false;
Element x = packet.getChildElement().element("x");
if (x != null && x.getNamespaceURI() != null && x.getNamespaceURI().equals(IQ_GATEWAY_REGISTER)) {
rosterlessMode = true;
Log.info("Registered " + packet.getFrom() + " as " + username + " in rosterless mode.");
}
else {
Log.info("Registered " + packet.getFrom() + " as " + username);
}
IQ result = IQ.createResultIQ(packet);
Element response = DocumentHelper.createElement(QName.get("query", IQ_REGISTER));
result.setChildElement(response);
reply.add(result);
try {
this.addNewRegistration(from, username, password, nickname, rosterlessMode);
}
catch (UserNotFoundException e) {
Log.error("Someone attempted to register with the gateway who is not registered with the server: " + from);
IQ eresult = IQ.createResultIQ(packet);
eresult.setError(Condition.forbidden);
reply.add(eresult);
Message em = new Message();
em.setType(Message.Type.error);
em.setTo(packet.getFrom());
em.setFrom(packet.getTo());
em.setBody(LocaleUtils.getLocalizedString("gateway.base.registrationdeniednoacct", "gateway"));
reply.add(em);
}
catch (IllegalAccessException e) {
Log.error("Someone who is not a user of this server tried to register with the transport: "+from);
IQ eresult = IQ.createResultIQ(packet);
eresult.setError(Condition.forbidden);
reply.add(eresult);
Message em = new Message();
em.setType(Message.Type.error);
em.setTo(packet.getFrom());
em.setFrom(packet.getTo());
em.setBody(LocaleUtils.getLocalizedString("gateway.base.registrationdeniedbyhost", "gateway"));
reply.add(em);
}
catch (IllegalArgumentException e) {
Log.error("Someone attempted to register with the gateway with an invalid username: " + from);
IQ eresult = IQ.createResultIQ(packet);
eresult.setError(Condition.bad_request);
reply.add(eresult);
Message em = new Message();
em.setType(Message.Type.error);
em.setTo(packet.getFrom());
em.setFrom(packet.getTo());
em.setBody(LocaleUtils.getLocalizedString("gateway.base.registrationdeniedbadusername", "gateway"));
reply.add(em);
}
}
}
else if (packet.getType() == IQ.Type.get) {
Element response = DocumentHelper.createElement(QName.get("query", IQ_REGISTER));
IQ result = IQ.createResultIQ(packet);
String curUsername = null;
String curPassword = null;
String curNickname = null;
Boolean registered = false;
Collection<Registration> registrations = registrationManager.getRegistrations(from, this.transportType);
if (registrations.iterator().hasNext()) {
Registration registration = registrations.iterator().next();
curUsername = registration.getUsername();
curPassword = registration.getPassword();
curNickname = registration.getNickname();
registered = true;
}
if (!registered && !permissionManager.hasAccess(from)) {
// User does not have permission to register with transport.
// We want to allow them to change settings if they are already registered.
result.setError(Condition.forbidden);
reply.add(result);
Message em = new Message();
em.setType(Message.Type.error);
em.setTo(packet.getFrom());
em.setFrom(packet.getTo());
em.setBody(LocaleUtils.getLocalizedString("gateway.base.registrationdeniedbyacls", "gateway"));
reply.add(em);
return reply;
}
DataForm form = new DataForm(DataForm.Type.form);
form.addInstruction(getTerminologyRegistration());
FormField usernameField = form.addField();
usernameField.setLabel(getTerminologyUsername());
usernameField.setVariable("username");
usernameField.setType(FormField.Type.text_single);
if (curUsername != null) {
usernameField.addValue(curUsername);
}
FormField passwordField = form.addField();
passwordField.setLabel(getTerminologyPassword());
passwordField.setVariable("password");
passwordField.setType(FormField.Type.text_private);
if (curPassword != null) {
passwordField.addValue(curPassword);
}
String nicknameTerm = getTerminologyNickname();
if (nicknameTerm != null) {
FormField nicknameField = form.addField();
nicknameField.setLabel(nicknameTerm);
nicknameField.setVariable("nick");
nicknameField.setType(FormField.Type.text_single);
if (curNickname != null) {
nicknameField.addValue(curNickname);
}
}
response.add(form.getElement());
response.addElement("instructions").addText(getTerminologyRegistration());
if (registered) {
response.addElement("registered");
response.addElement("username").addText(curUsername);
if (curPassword == null) {
response.addElement("password");
}
else {
response.addElement("password").addText(curPassword);
}
if (nicknameTerm != null) {
if (curNickname == null) {
response.addElement("nick");
}
else {
response.addElement("nick").addText(curNickname);
}
}
}
else {
response.addElement("username");
response.addElement("password");
if (nicknameTerm != null) {
response.addElement("nick");
}
}
// Add special indicator for rosterless gateway handling.
response.addElement("x").addNamespace("", IQ_GATEWAY_REGISTER);
result.setChildElement(response);
reply.add(result);
}
}
return reply;
}
/**
* Handle version request.
*
* @param packet An IQ packet in the iq version namespace.
* @return A list of IQ packets to be returned to the user.
*/
private List<Packet> handleIQVersion(IQ packet) {
List<Packet> reply = new ArrayList<Packet>();
if (packet.getType() == IQ.Type.get) {
IQ result = IQ.createResultIQ(packet);
Element query = DocumentHelper.createElement(QName.get("query", IQ_VERSION));
query.addElement("name").addText("Openfire " + this.getDescription());
query.addElement("version").addText(XMPPServer.getInstance().getServerInfo().getVersion().getVersionString() + " - " + this.getVersionString());
query.addElement("os").addText(System.getProperty("os.name"));
result.setChildElement(query);
reply.add(result);
}
return reply;
}
/**
* Converts a legacy username to a JID.
*
* @param username Username to be converted to a JID.
* @return The legacy username as a JID.
*/
public JID convertIDToJID(String username) {
if (JiveGlobals.getBooleanProperty("plugin.gateway.tweak.percenthack", false)) {
return new JID(username.replace('@', '%').replace(" ", ""), this.jid.getDomain(), null);
}
else {
return new JID(JID.escapeNode(username.replace(" ", "")), this.jid.getDomain(), null);
}
}
/**
* Converts a JID to a legacy username.
*
* @param jid JID to be converted to a legacy username.
* @return THe legacy username as a String.
*/
public String convertJIDToID(JID jid) {
if (JiveGlobals.getBooleanProperty("plugin.gateway.tweak.percenthack", false)) {
return jid.getNode().replace('%', '@');
}
else {
return JID.unescapeNode(jid.getNode());
}
}
/**
* Gets an easy to use presence type from a presence packet.
*
* @param packet A presence packet from which the type will be pulled.
* @return the presence type of the specified packet.
*/
public PresenceType getPresenceType(Presence packet) {
Presence.Type ptype = packet.getType();
Presence.Show stype = packet.getShow();
if (stype == Presence.Show.chat) {
return PresenceType.chat;
}
else if (stype == Presence.Show.away) {
return PresenceType.away;
}
else if (stype == Presence.Show.xa) {
return PresenceType.xa;
}
else if (stype == Presence.Show.dnd) {
return PresenceType.dnd;
}
else if (ptype == Presence.Type.unavailable) {
return PresenceType.unavailable;
}
else if (packet.isAvailable()) {
return PresenceType.available;
}
else {
return PresenceType.unknown;
}
}
/**
* Handles startup of the transport.
*/
public void start() {
RosterEventDispatcher.addListener(this);
// PresenceEventDispatcher.addListener(this);
// Probe all registered users [if they are logged in] to auto-log them in
for (Registration registration : registrationManager.getRegistrations()) {
if (SessionManager.getInstance().getSessionCount(registration.getJID().getNode()) > 0) {
Presence p = new Presence(Presence.Type.probe);
p.setFrom(this.getJID());
p.setTo(registration.getJID());
sendPacket(p);
}
}
}
/**
* Handles shutdown of the transport.
*
* Cleans up all active sessions.
*/
public void shutdown() {
RosterEventDispatcher.removeListener(this);
// PresenceEventDispatcher.removeListener(this);
// Disconnect everyone's session
for (TransportSession session : sessionManager.getSessions()) {
registrationLoggedOut(session);
session.removeAllResources();
}
sessionManager.shutdown();
}
/**
* Returns the jid of the transport.
*
* @return the jid of the transport.
*/
public JID getJID() {
return this.jid;
}
/**
* Returns the roster manager for the transport.
*
* @return the roster manager for the transport.
*/
public RosterManager getRosterManager() {
return this.rosterManager;
}
/**
* Returns the name (type) of the transport.
*/
public String getName() {
return transportType.toString();
}
/**
* @return the type of the transport.
*/
public TransportType getType() {
return transportType;
}
/**
* @return the description of the transport.
*/
public String getDescription() {
return description;
}
/**
* @return the component manager of the transport.
*/
public ComponentManager getComponentManager() {
return componentManager;
}
/**
* @return the registration manager of the transport.
*/
public RegistrationManager getRegistrationManager() {
return registrationManager;
}
/**
* @return the session manager of the transport.
*/
public TransportSessionManager getSessionManager() {
return sessionManager;
}
/**
* Retains the version string for later requests.
*/
private String versionString = null;
/**
* @return the version string of the gateway.
*/
public String getVersionString() {
if (versionString == null) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
versionString = pluginManager.getVersion(pluginManager.getPlugin("gateway"));
}
return versionString;
}
/**
* Either updates or adds a JID to a user's roster.
*
* Tries to only edit the roster if it has to.
*
* @param userjid JID of user to have item added to their roster.
* @param contactjid JID to add to roster.
* @param nickname Nickname of item. (can be null)
* @param groups List of group the item is to be placed in. (can be null)
* @throws UserNotFoundException if userjid not found.
*/
public void addOrUpdateRosterItem(JID userjid, JID contactjid, String nickname, List<String> groups) throws UserNotFoundException {
try {
Roster roster = rosterManager.getRoster(userjid.getNode());
try {
RosterItem gwitem = roster.getRosterItem(contactjid);
boolean changed = false;
if (gwitem.getSubStatus() != RosterItem.SUB_BOTH) {
gwitem.setSubStatus(RosterItem.SUB_BOTH);
changed = true;
}
if (gwitem.getAskStatus() != RosterItem.ASK_NONE) {
gwitem.setAskStatus(RosterItem.ASK_NONE);
changed = true;
}
// This could probably be simplified, for now I'm going with brute force logic.
// gnickname is null, nickname is null, leave
// gnickname is not null, nickname is null, set gnickname to null
// gnickname is null, nickname is not null, set gnickname to nickname
// gnickname is not null, nickname is not null, if different, set gnickname to nickname
if ( (gwitem.getNickname() != null && nickname == null) ||
(gwitem.getNickname() == null && nickname != null) ||
(gwitem.getNickname() != null && nickname != null && !gwitem.getNickname().equals(nickname))) {
gwitem.setNickname(nickname);
changed = true;
}
List<String> curgroups = gwitem.getGroups();
if (curgroups != groups) {
try {
gwitem.setGroups(groups);
changed = true;
}
catch (Exception ee) {
// Oooookay, ignore then.
}
}
if (changed) {
roster.updateRosterItem(gwitem);
}
}
catch (UserNotFoundException e) {
try {
// Create new roster item for the gateway service or legacy contact. Only
// roster items related to the gateway service will be persistent. Roster
// items of legacy users are never persisted in the DB.
RosterItem gwitem =
roster.createRosterItem(contactjid, true, contactjid.getNode() == null);
gwitem.setSubStatus(RosterItem.SUB_BOTH);
gwitem.setAskStatus(RosterItem.ASK_NONE);
gwitem.setNickname(nickname);
try {
gwitem.setGroups(groups);
}
catch (Exception ee) {
// Oooookay, ignore then.
}
roster.updateRosterItem(gwitem);
}
catch (UserAlreadyExistsException ee) {
Log.error("getRosterItem claims user exists, but couldn't find via getRosterItem?", ee);
}
catch (Exception ee) {
Log.error("Exception while creating roster item:", ee);
}
}
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Could not find roster for " + userjid.toString());
}
}
/**
* Either updates or adds a JID to a user's roster.
*
* Tries to only edit the roster if it has to.
*
* @param userjid JID of user to have item added to their roster.
* @param contactjid JID to add to roster.
* @param nickname Nickname of item. (can be null)
* @param group Group item is to be placed in. (can be null)
* @throws UserNotFoundException if userjid not found.
*/
public void addOrUpdateRosterItem(JID userjid, JID contactjid, String nickname, String group) throws UserNotFoundException {
ArrayList<String> groups = null;
if (group != null) {
groups = new ArrayList<String>();
groups.add(group);
}
addOrUpdateRosterItem(userjid, contactjid, nickname, groups);
}
/**
* Either updates or adds a contact to a user's roster.
*
* @param userjid JID of user to have item added to their roster.
* @param contactid String contact name, will be translated to JID.
* @param nickname Nickname of item. (can be null)
* @param group Group item is to be placed in. (can be null)
* @throws UserNotFoundException if userjid not found.
*/
public void addOrUpdateRosterItem(JID userjid, String contactid, String nickname, String group) throws UserNotFoundException {
try {
addOrUpdateRosterItem(userjid, convertIDToJID(contactid), nickname, group);
}
catch (UserNotFoundException e) {
// Pass it on down.
throw e;
}
}
/**
* Removes a roster item from a user's roster.
*
* @param userjid JID of user whose roster we will interact with.
* @param contactjid JID to be removed from roster.
* @throws UserNotFoundException if userjid not found.
*/
public void removeFromRoster(JID userjid, JID contactjid) throws UserNotFoundException {
// Clean up the user's contact list.
try {
Roster roster = rosterManager.getRoster(userjid.getNode());
for (RosterItem ri : roster.getRosterItems()) {
if (ri.getJid().toBareJID().equals(contactjid.toBareJID())) {
try {
roster.deleteRosterItem(ri.getJid(), false);
}
catch (Exception e) {
Log.error("Error removing roster item: " + ri.toString(), e);
}
}
}
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Could not find roster for " + userjid.toString());
}
}
/**
* Removes a roster item from a user's roster based on a legacy contact.
*
* @param userjid JID of user whose roster we will interact with.
* @param contactid Contact to be removed, will be translated to JID.
* @throws UserNotFoundException if userjid not found.
*/
void removeFromRoster(JID userjid, String contactid) throws UserNotFoundException {
// Clean up the user's contact list.
try {
removeFromRoster(userjid, convertIDToJID(contactid));
}
catch (UserNotFoundException e) {
// Pass it on through.
throw e;
}
}
/**
* Sync a user's roster with their legacy contact list.
*
* Given a collection of transport buddies, syncs up the user's
* roster by fixing any nicknames, group assignments, adding and removing
* roster items, and generally trying to make the jabber roster list
* assigned to the transport's JID look at much like the legacy buddy
* list as possible. This is a very extensive operation. You do not
* want to do this very often. Typically once right after the person
* has logged into the legacy service.
*
* @param userjid JID of user who's roster we are syncing with.
* @param legacyitems List of TransportBuddy's to be synced.
* @throws UserNotFoundException if userjid not found.
*/
public void syncLegacyRoster(JID userjid, List<TransportBuddy> legacyitems) throws UserNotFoundException {
try {
Roster roster = rosterManager.getRoster(userjid.getNode());
// Lets lock down the roster from update notifications if there's an active session.
try {
TransportSession session = sessionManager.getSession(userjid.getNode());
session.lockRoster();
}
catch (NotFoundException e) {
// No active session? Then no problem.
}
// First thing first, we want to build ourselves an easy mapping.
Map<JID,TransportBuddy> legacymap = new HashMap<JID,TransportBuddy>();
for (TransportBuddy buddy : legacyitems) {
//Log.debug("ROSTERSYNC: Mapping "+buddy.getName());
legacymap.put(convertIDToJID(buddy.getName()), buddy);
}
// Now, lets go through the roster and see what matches up.
for (RosterItem ri : roster.getRosterItems()) {
if (!ri.getJid().getDomain().equals(this.jid.getDomain())) {
// Not our contact to care about.
continue;
}
if (ri.getJid().getNode() == null) {
// This is a transport instance, lets leave it alone.
continue;
}
JID jid = new JID(ri.getJid().toBareJID());
if (legacymap.containsKey(jid)) {
//Log.debug("ROSTERSYNC: We found, updating " + jid.toString());
// Ok, matched a legacy to jabber roster item
// Lets update if there are differences
TransportBuddy buddy = legacymap.get(jid);
try {
this.addOrUpdateRosterItem(userjid, buddy.getName(), buddy.getNickname(), buddy.getGroup());
}
catch (UserNotFoundException e) {
Log.error("Failed updating roster item", e);
}
legacymap.remove(jid);
}
else {
//Log.debug("ROSTERSYNC: We did not find, removing " + jid.toString());
// This person is apparantly no longer in the legacy roster.
try {
this.removeFromRoster(userjid, jid);
}
catch (UserNotFoundException e) {
Log.error("Failed removing roster item", e);
}
}
}
// Ok, we should now have only new items from the legacy roster
for (TransportBuddy buddy : legacymap.values()) {
//Log.debug("ROSTERSYNC: We have new, adding " + buddy.getName());
try {
this.addOrUpdateRosterItem(userjid, buddy.getName(), buddy.getNickname(), buddy.getGroup());
}
catch (UserNotFoundException e) {
Log.error("Failed adding new roster item", e);
}
}
// All done, lets unlock the roster.
try {
TransportSession session = sessionManager.getSession(userjid.getNode());
session.unlockRoster();
}
catch (NotFoundException e) {
// No active session? Then no problem.
}
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Could not find roster for " + userjid.toString());
}
}
/**
* Adds a registration with this transport.
*
* @param jid JID of user to add registration to.
* @param username Legacy username of registration.
* @param password Legacy password of registration.
* @param nickname Legacy nickname of registration.
* @param noRosterItem True if the transport is not to show up in the user's roster.
* @throws UserNotFoundException if registration or roster not found.
* @throws IllegalAccessException if jid is not from this server.
* @throws IllegalArgumentException if username is not valid for this transport type.
*/
public void addNewRegistration(JID jid, String username, String password, String nickname, Boolean noRosterItem) throws UserNotFoundException, IllegalAccessException {
if (!XMPPServer.getInstance().getServerInfo().getName().equals(jid.getDomain())) {
throw new IllegalAccessException("Domain of jid registering does not match domain of server.");
}
if (!isUsernameValid(username)) {
throw new IllegalArgumentException("Username specified is not valid for this transport type.");
}
Collection<Registration> registrations = registrationManager.getRegistrations(jid, this.transportType);
Boolean foundReg = false;
for (Registration registration : registrations) {
if (!registration.getUsername().equals(username)) {
registrationManager.deleteRegistration(registration);
}
else {
registration.setPassword(password);
foundReg = true;
}
try {
TransportSession relatedSession = sessionManager.getSession(registration.getJID().getNode());
this.registrationLoggedOut(relatedSession);
}
catch (NotFoundException e) {
// No worries, move on.
}
}
if (!foundReg) {
registrationManager.createRegistration(jid, this.transportType, username, password, nickname);
}
// Clean up any leftover roster items from other transports.
try {
cleanUpRoster(jid, !noRosterItem);
}
catch (UserNotFoundException ee) {
throw new UserNotFoundException("Unable to find roster.");
}
if (!noRosterItem) {
try {
addOrUpdateRosterItem(jid, this.getJID(), this.getDescription(), "Transports");
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("User not registered with server.");
}
}
// Lets ask them what their presence is, maybe log them in immediately.
Presence p = new Presence(Presence.Type.probe);
p.setTo(jid);
p.setFrom(getJID());
sendPacket(p);
}
/**
* Removes a registration from this transport.
*
* @param jid JID of user to add registration to.
* @throws UserNotFoundException if registration or roster not found.
*/
public void deleteRegistration(JID jid) throws UserNotFoundException {
Collection<Registration> registrations = registrationManager.getRegistrations(jid, this.transportType);
if (registrations.isEmpty()) {
throw new UserNotFoundException("User was not registered.");
}
// Log out any active sessions.
try {
TransportSession session = sessionManager.getSession(jid);
if (session.isLoggedIn()) {
this.registrationLoggedOut(session);
}
sessionManager.removeSession(jid);
}
catch (NotFoundException e) {
// Ok then.
}
// For now, we're going to have to just nuke all of these. Sorry.
for (Registration reg : registrations) {
registrationManager.deleteRegistration(reg);
}
// Clean up the user's contact list.
try {
cleanUpRoster(jid, false, true);
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Unable to find roster.");
}
}
/**
* Cleans a roster of entries related to this transport.
*
* This function will run through the roster of the specified user and clean up any
* entries that share the domain of this transport. Depending on the removeNonPersistent
* option, it will either leave or keep the non-persistent 'contact' entries.
*
* @param jid JID of the user whose roster we want to clean up.
* @param leaveDomain If set, we do not touch the roster item associated with the domain itself.
* @param removeNonPersistent If set, we will also remove non-persistent items.
* @throws UserNotFoundException if the user is not found.
*/
public void cleanUpRoster(JID jid, Boolean leaveDomain, Boolean removeNonPersistent) throws UserNotFoundException {
try {
Roster roster = rosterManager.getRoster(jid.getNode());
// Lets lock down the roster from update notifications if there's an active session.
try {
TransportSession session = sessionManager.getSession(jid.getNode());
session.lockRoster();
}
catch (NotFoundException e) {
// No active session? Then no problem.
}
for (RosterItem ri : roster.getRosterItems()) {
if (ri.getJid().getDomain().equals(this.jid.getDomain())) {
if (ri.isShared()) { // Is a shared item we can't really touch.
continue;
}
if (!removeNonPersistent && ri.getID() == 0) { // Is a non-persistent roster item.
continue;
}
if (leaveDomain && ri.getJid().getNode() == null) { // The actual transport domain item.
continue;
}
try {
Log.debug("Cleaning up roster entry " + ri.getJid().toString());
roster.deleteRosterItem(ri.getJid(), false);
}
catch (Exception e) {
Log.error("Error removing roster item: " + ri.toString(), e);
}
}
}
// All done, lets unlock the roster.
try {
TransportSession session = sessionManager.getSession(jid.getNode());
session.unlockRoster();
}
catch (NotFoundException e) {
// No active session? Then no problem.
}
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Unable to find roster.");
}
}
/**
* Cleans a roster of entries related to this transport that are not shared.
*
* This function will run through the roster of the specified user and clean up any
* entries that share the domain of this transport. This is primarily used during registration
* to clean up leftovers from other transports.
*
* @param jid JID of user whose roster we want to clean up.
* @param leaveDomain If set, we do not touch the roster item associated with the domain itself.
* @throws UserNotFoundException if the user is not found.
*/
public void cleanUpRoster(JID jid, Boolean leaveDomain) throws UserNotFoundException {
try {
cleanUpRoster(jid, leaveDomain, false);
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Unable to find roster.");
}
}
/**
* Sends offline packets for an entire roster to the target user.
*
* This function will run through the roster of the specified user and send offline
* presence packets for each roster item. This is typically used when a user logs
* off so that all of the associated roster items appear offline. This also sends
* the unavailable presence for the transport itself.
*
* @param jid JID of user whose roster we want to clean up.
* @throws UserNotFoundException if the user is not found.
*/
public void notifyRosterOffline(JID jid) throws UserNotFoundException {
try {
Roster roster = rosterManager.getRoster(jid.getNode());
for (RosterItem ri : roster.getRosterItems()) {
if (ri.getJid().getDomain().equals(this.jid.getDomain())) {
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(jid);
p.setFrom(ri.getJid());
sendPacket(p);
}
}
}
catch (UserNotFoundException e) {
throw new UserNotFoundException("Unable to find roster.");
}
}
/**
* Sends a packet through the component manager as the component.
*
* @param packet Packet to be sent.
*/
public void sendPacket(Packet packet) {
Log.debug(getType().toString()+": Sending packet: "+packet.toXML());
try {
this.componentManager.sendPacket(this, packet);
}
catch (Exception e) {
Log.error("Failed to deliver packet: " + packet.toString());
}
}
/**
* Sends a simple message through he component manager.
*
* @param to Who the message is for.
* @param from Who the message is from.
* @param msg Message to be send.
* @param type Type of message to be sent.
*/
public void sendMessage(JID to, JID from, String msg, Message.Type type) {
Message m = new Message();
m.setType(type);
m.setFrom(from);
m.setTo(to);
m.setBody(msg);
if (type.equals(Message.Type.chat) || type.equals(Message.Type.normal)) {
Element xEvent = m.addChildElement("x", "jabber:x:event");
// xEvent.addElement("id");
xEvent.addElement("composing");
m.addChildElement("active", CHATSTATES);
}
sendPacket(m);
}
/**
* Sends a simple message through the component manager.
*
* @param to Who the message is for.
* @param from Who the message is from.
* @param msg Message to be send.
*/
public void sendMessage(JID to, JID from, String msg) {
sendMessage(to, from, msg, Message.Type.chat);
}
/**
* Sends a typing notification the component manager.
*
* This will check whether the person supports typing notifications before sending.
* TODO: actually check for typing notification support
*
* @param to Who the notification is for.
* @param from Who the notification is from.
*/
public void sendComposingNotification(JID to, JID from) {
Message m = new Message();
m.setType(Message.Type.chat);
m.setTo(to);
m.setFrom(from);
Element xEvent = m.addChildElement("x", "jabber:x:event");
xEvent.addElement("id");
xEvent.addElement("composing");
m.addChildElement("composing", CHATSTATES);
sendPacket(m);
}
/**
* Sends a typing paused notification the component manager.
*
* This will check whether the person supports typing notifications before sending.
* TODO: actually check for typing notification support
*
* @param to Who the notification is for.
* @param from Who the notification is from.
*/
public void sendComposingPausedNotification(JID to, JID from) {
Message m = new Message();
m.setType(Message.Type.chat);
m.setTo(to);
m.setFrom(from);
m.addChildElement("paused", CHATSTATES);
sendPacket(m);
}
/**
* Sends an inactive chat session notification the component manager.
*
* This will check whether the person supports typing notifications before sending.
* TODO: actually check for typing notification support
*
* @param to Who the notification is for.
* @param from Who the notification is from.
*/
public void sendChatInactiveNotification(JID to, JID from) {
Message m = new Message();
m.setType(Message.Type.chat);
m.setTo(to);
m.setFrom(from);
m.addChildElement("inactive", CHATSTATES);
sendPacket(m);
}
/**
* Sends a gone chat session notification the component manager.
*
* This will check whether the person supports typing notifications before sending.
* TODO: actually check for typing notification support
*
* @param to Who the notification is for.
* @param from Who the notification is from.
*/
public void sendChatGoneNotification(JID to, JID from) {
Message m = new Message();
m.setType(Message.Type.chat);
m.setTo(to);
m.setFrom(from);
m.addChildElement("gone", CHATSTATES);
sendPacket(m);
}
/**
* Intercepts roster additions related to the gateway and flags them as non-persistent.
*
* @see org.jivesoftware.openfire.roster.RosterEventListener#addingContact(org.jivesoftware.openfire.roster.Roster, org.jivesoftware.openfire.roster.RosterItem, boolean)
*/
public boolean addingContact(Roster roster, RosterItem item, boolean persistent) {
if (item.getJid().getDomain().equals(this.getJID().toString()) && item.getJid().getNode() != null) {
return false;
}
return persistent;
}
/**
* Handles updates to a roster item that are not normally forwarded to the transport.
*
* @see org.jivesoftware.openfire.roster.RosterEventListener#contactUpdated(org.jivesoftware.openfire.roster.Roster, org.jivesoftware.openfire.roster.RosterItem)
*/
public void contactUpdated(Roster roster, RosterItem item) {
if (!item.getJid().getDomain().equals(this.getJID().getDomain())) {
// Not ours, not our problem.
return;
}
if (item.getJid().getNode() == null) {
// Gateway itself, don't care.
return;
}
try {
TransportSession session = sessionManager.getSession(roster.getUsername());
if (!session.isRosterLocked(item.getJid().toString())) {
Log.debug(getType().toString()+": contactUpdated "+roster.getUsername()+":"+item.getJid());
session.updateContact(item);
}
}
catch (NotFoundException e) {
// Well we just don't care then.
}
}
/**
* Handles additions to a roster. We don't really care because we hear about these via subscribes.
*
* @see org.jivesoftware.openfire.roster.RosterEventListener#contactAdded(org.jivesoftware.openfire.roster.Roster, org.jivesoftware.openfire.roster.RosterItem)
*/
public void contactAdded(Roster roster, RosterItem item) {
if (!item.getJid().getDomain().equals(this.getJID().getDomain())) {
// Not ours, not our problem.
return;
}
if (item.getJid().getNode() == null) {
// Gateway itself, don't care.
return;
}
try {
TransportSession session = sessionManager.getSession(roster.getUsername());
if (!session.isRosterLocked(item.getJid().toString())) {
Log.debug(getType().toString()+": contactAdded "+roster.getUsername()+":"+item.getJid());
session.addContact(item);
}
}
catch (NotFoundException e) {
// Well we just don't care then.
}
}
/**
* Handles deletions from a roster. We don't really care because we hear about these via unsubscribes.
*
* @see org.jivesoftware.openfire.roster.RosterEventListener#contactDeleted(org.jivesoftware.openfire.roster.Roster, org.jivesoftware.openfire.roster.RosterItem)
*/
public void contactDeleted(Roster roster, RosterItem item) {
if (!item.getJid().getDomain().equals(this.getJID().getDomain())) {
// Not ours, not our problem.
return;
}
if (item.getJid().getNode() == null) {
// Gateway itself, don't care.
return;
}
try {
TransportSession session = sessionManager.getSession(roster.getUsername());
if (!session.isRosterLocked(item.getJid().toString())) {
Log.debug(getType().toString()+": contactDeleted "+roster.getUsername()+":"+item.getJid());
session.removeContact(item);
}
}
catch (NotFoundException e) {
// Well we just don't care then.
}
}
/**
* Handles notifications of a roster being loaded. Not sure we care.
*
* @see org.jivesoftware.openfire.roster.RosterEventListener#rosterLoaded(org.jivesoftware.openfire.roster.Roster)
*/
public void rosterLoaded(Roster roster) {
Log.debug(getType().toString()+": rosterLoaded "+roster.getUsername());
// Don't care
}
/**
* Will handle logging in to the legacy service.
*
* @param registration Registration used for log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
* @param priority Priority of the session (from presence packet).
* @return A session instance for the new login.
*/
public abstract TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority);
/**
* Will handle logging out of the legacy service.
*
* @param session TransportSession to be logged out.
*/
public abstract void registrationLoggedOut(TransportSession session);
/**
* Returns the terminology used for a username on the legacy service.
*
* @return String term for username.
*/
public abstract String getTerminologyUsername();
/**
* Returns the terminology used for a password on the legacy service.
*
* @return String term for password.
*/
public abstract String getTerminologyPassword();
/**
* Returns the terminology used for a nickname on the legacy service.
*
* You can return null to indicate that this is not supported by the legacy service.
*
* @return String term for nickname.
*/
public abstract String getTerminologyNickname();
/**
* Returns instructions for registration in legacy complient terminology.
*
* You would write this out as if the entry textfields for the username and password
* are after it/on the same page. So something along these lines would be good:
* Please enter your legacy username and password.
*
* @return String phrase for registration.
*/
public abstract String getTerminologyRegistration();
/**
* Is a password required for this service?
*
* @return True or false whether the password is required.
*/
public abstract Boolean isPasswordRequired();
/**
* Is a nickname required for this service?
*
* @return True or false whether the nickname is required.
*/
public abstract Boolean isNicknameRequired();
/**
* Is the specified username valid?
*
* @param username Username to validate.
* @return True or false whether the passed username is valud for the service.
*/
public abstract Boolean isUsernameValid(String username);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* An enumeration for different chat state types.
*
* This class contains a list of all of the possible chat states.
*
* @author Daniel Henninger
*/
public enum ChatStateType {
/**
* Active (user is actively participating in a conversation)
*/
active,
/**
* Composing (user is currently composing a message)
*/
composing,
/**
* Paused (user has paused while composing a message)
*/
paused,
/**
* Inactive (user has not interacted with the chat session for a short period of time)
*/
inactive,
/**
* Gone (user has not interacted with the chat session for a long period of time)
*/
gone
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.defaults.DefaultPicoContainer;
import org.dom4j.DocumentHelper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.Hashtable;
/**
* IM Gateway plugin, which provides connectivity to IM networks that
* don't support the XMPP protocol.
*
* The entire plugin is referred to as the gateway, while individual
* IM network mappings are referred to as transports.
*
* @author Daniel Henninger
*/
public class GatewayPlugin implements Plugin {
private MutablePicoContainer picoContainer;
private File pluginDirectory;
private PluginManager pluginManager;
/**
* Represents all configured transport handlers.
*/
public Hashtable<String,TransportInstance> transports;
public GatewayPlugin() {
picoContainer = new DefaultPicoContainer();
picoContainer.registerComponentImplementation(RegistrationManager.class);
}
public void initializePlugin(PluginManager manager, File pluginDirectory) {
this.pluginDirectory = pluginDirectory;
this.pluginManager = manager;
picoContainer.start();
transports = new Hashtable<String,TransportInstance>();
ComponentManager componentManager = ComponentManagerFactory.getComponentManager();
/* Set up AIM transport. */
transports.put("aim", new TransportInstance(TransportType.aim, LocaleUtils.getLocalizedString("gateway.aim.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.oscar.OSCARTransport", componentManager));
maybeStartService("aim");
/* Set up ICQ transport. */
transports.put("icq", new TransportInstance(TransportType.icq, LocaleUtils.getLocalizedString("gateway.icq.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.oscar.OSCARTransport", componentManager));
maybeStartService("icq");
/* Set up IRC transport. */
transports.put("irc", new TransportInstance(TransportType.irc, LocaleUtils.getLocalizedString("gateway.irc.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.irc.IRCTransport", componentManager));
maybeStartService("irc");
/* Set up Yahoo transport. */
transports.put("yahoo", new TransportInstance(TransportType.yahoo, LocaleUtils.getLocalizedString("gateway.yahoo.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.yahoo.YahooTransport", componentManager));
maybeStartService("yahoo");
/* Set up MSN transport. */
transports.put("msn", new TransportInstance(TransportType.msn, LocaleUtils.getLocalizedString("gateway.msn.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.msn.MSNTransport", componentManager));
maybeStartService("msn");
/* Set up XMPP transport. */
transports.put("xmpp", new TransportInstance(TransportType.xmpp, LocaleUtils.getLocalizedString("gateway.xmpp.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.xmpp.XMPPTransport", componentManager));
maybeStartService("xmpp");
/* Set up GTalk transport. */
transports.put("gtalk", new TransportInstance(TransportType.gtalk, LocaleUtils.getLocalizedString("gateway.gtalk.name", "gateway"), "org.jivesoftware.openfire.gateway.protocols.xmpp.XMPPTransport", componentManager));
maybeStartService("gtalk");
}
public void destroyPlugin() {
for (TransportInstance trInstance : transports.values()) {
trInstance.stopInstance();
}
picoContainer.stop();
picoContainer.dispose();
picoContainer = null;
}
/**
* Returns the instance of a module registered with the plugin.
*
* @param clazz the module class.
* @return the instance of the module.
*/
public Object getModule(Class clazz) {
return picoContainer.getComponentInstanceOfType(clazz);
}
/**
* Returns the plugin manager handling the plugin.
*
* @return plugin manager in question.
*/
public PluginManager getPluginManager() {
return pluginManager;
}
/**
* Starts a transport service, identified by subdomain. The transport
* service will only start if it is enabled.
*
* @param serviceName name of service to start.
*/
private void maybeStartService(String serviceName) {
TransportInstance trInstance = transports.get(serviceName);
trInstance.startInstance();
}
/**
* Enables a transport service, identified by subdomain.
*
* @param serviceName name of service to enable.
*/
public void enableService(String serviceName) {
TransportInstance trInstance = transports.get(serviceName);
trInstance.enable();
}
/**
* Disables a transport service, identified by subdomain.
*
* @param serviceName name of service to disable.
*/
public void disableService(String serviceName) {
TransportInstance trInstance = transports.get(serviceName);
trInstance.disable();
}
/**
* Returns the state of a transport service, identified by subdomain.
*
* @param serviceName name of service to check.
* @return True of false if service is enabled.
*/
public Boolean serviceEnabled(String serviceName) {
TransportInstance trInstance = transports.get(serviceName);
return trInstance.isEnabled();
}
/**
* Returns the transport instance, identified by subdomain.
*
* @param serviceName name of service to get instance of.
* @return Instance of service requested.
*/
public TransportInstance getTransportInstance(String serviceName) {
return transports.get(serviceName);
}
/**
* Returns the web options config for the given transport, if it exists.
*
* @param type type of the transport we want the options config for.
* @return XML document with the options config.
*/
public Document getOptionsConfig(TransportType type) {
// Load any custom-defined servlets.
File optConf = new File(this.pluginDirectory, "web" + File.separator + "WEB-INF" +
File.separator + "options" + File.separator + type.toString() + ".xml");
Document optConfXML;
try {
FileReader reader = new FileReader(optConf);
SAXReader xmlReader = new SAXReader();
xmlReader.setEncoding("UTF-8");
optConfXML = xmlReader.read(reader);
}
catch (FileNotFoundException e) {
// Non-existent: Return empty config
optConfXML = DocumentHelper.createDocument();
optConfXML.addElement("optionsconfig");
}
catch (DocumentException e) {
// Bad config: Return empty config
optConfXML = DocumentHelper.createDocument();
optConfXML.addElement("optionsconfig");
}
return optConfXML;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.user.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
/**
* Registration Permissions Manager
*
* Handles who has access to a given transport, both for checking access and for
* managing who is in the access list. Should be used regardless of whether permissions
* are set to "all" or "none" or not as this class checks for those settings on it's own.
*
* @author Daniel Henninger
*/
public class PermissionManager {
private static final String IS_USER_LISTED =
"SELECT count(*) FROM gatewayRestrictions WHERE transportType=? AND username=?";
private static final String GROUPS_LISTED =
"SELECT groupname FROM gatewayRestrictions WHERE transportType=?";
private static final String DELETE_ALL_USERS =
"DELETE FROM gatewayRestrictions WHERE transportType=? AND username IS NOT NULL";
private static final String DELETE_ALL_GROUPS =
"DELETE FROM gatewayRestrictions WHERE transportType=? AND groupname IS NOT NULL";
private static final String ADD_NEW_USER =
"INSERT INTO gatewayRestrictions(transportType,username) VALUES(?,?)";
private static final String ADD_NEW_GROUP =
"INSERT INTO gatewayRestrictions(transportType,groupname) VALUES(?,?)";
private static final String GET_ALL_USERS =
"SELECT username FROM gatewayRestrictions WHERE transportType=? AND username IS NOT NULL ORDER BY username";
private static final String GET_ALL_GROUPS =
"SELECT groupname FROM gatewayRestrictions WHERE transportType=? AND groupname IS NOT NULL ORDER BY groupname";
private TransportType transportType = null;
/**
* Create a permissionManager instance.
*
* @param type Type of the transport that this permission manager serves.
*/
public PermissionManager(TransportType type) {
this.transportType = type;
}
/**
* Checks if a user has access to the transport, via a number of methods.
*
* @param jid JID of the user who may or may not have access.
* @return True or false if the user has access.
*/
public boolean hasAccess(JID jid) {
int setting = JiveGlobals.getIntProperty("plugin.gateway."+transportType.toString()+".registration", 1);
if (setting == 1) { return true; }
if (setting == 3) { return false; }
if (isUserAllowed(jid)) { return true; }
if (isUserInAllowedGroup(jid)) { return true; }
return false;
}
/**
* Checks if a user has specific access to the transport.
*
* @param jid JID of the user who may or may not have access.
* @return True or false of the user has access.
*/
public boolean isUserAllowed(JID jid) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(IS_USER_LISTED);
pstmt.setString(1, transportType.toString());
pstmt.setString(2, jid.getNode());
rs = pstmt.executeQuery();
rs.next();
return (rs.getInt(1) > 0);
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return false;
}
/**
* Checks if a user is in a group that has access to the transport.
*
* @param jid JID of the user who may or may not have access.
* @return True or false of the user is in a group that has access.
*/
public boolean isUserInAllowedGroup(JID jid) {
ArrayList<String> allowedGroups = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GROUPS_LISTED);
pstmt.setString(1, transportType.toString());
rs = pstmt.executeQuery();
while (rs.next()) {
allowedGroups.add(rs.getString(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
Collection<Group> userGroups = GroupManager.getInstance().getGroups(jid);
for (Group g : userGroups) {
if (allowedGroups.contains(g.getName())) {
return true;
}
}
return false;
}
/**
* Stores a list of users as having access to the transport in question.
*
* @param users list of users who should have access.
*/
public void storeUserList(ArrayList<User> users) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_ALL_USERS);
pstmt.setString(1, transportType.toString());
pstmt.executeUpdate();
pstmt.close();
pstmt = con.prepareStatement(ADD_NEW_USER);
pstmt.setString(1, transportType.toString());
for (User user : users) {
pstmt.setString(2, user.getUsername());
pstmt.executeUpdate();
}
pstmt.close();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Stores a list of groups as having access to the transport in question.
*
* @param groups list of groups who should have access.
*/
public void storeGroupList(ArrayList<Group> groups) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_ALL_GROUPS);
pstmt.setString(1, transportType.toString());
pstmt.executeUpdate();
pstmt.close();
pstmt = con.prepareStatement(ADD_NEW_GROUP);
pstmt.setString(1, transportType.toString());
for (Group group : groups) {
pstmt.setString(2, group.getName());
pstmt.executeUpdate();
}
pstmt.close();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Retrieves a list of all of the users permitted to access this transport.
*
* @return List of users (as strings)
*/
public ArrayList<String> getAllUsers() {
ArrayList<String> userList = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_ALL_USERS);
pstmt.setString(1, transportType.toString());
rs = pstmt.executeQuery();
while (rs.next()) {
userList.add(rs.getString(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return userList;
}
/**
* Retrieves a list of all of the groups permitted to access this transport.
*
* @return List of groups (as strings)
*/
public ArrayList<String> getAllGroups() {
ArrayList<String> groupList = new ArrayList<String>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_ALL_GROUPS);
pstmt.setString(1, transportType.toString());
rs = pstmt.executeQuery();
while (rs.next()) {
groupList.add(rs.getString(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return groupList;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* An enumeration for different presence types.
*
* This is combined into a single variable, which is differnet than the
* typical situation of having to determine the status by looking at both
* the presence stanza's type and show fields.
*
* @author Daniel Henninger
*/
public enum PresenceType {
/**
* Available (aka online)
*/
available,
/**
* Away
*/
away,
/**
* XA (extended away)
*/
xa,
/**
* DND (do not disturb)
*/
dnd,
/**
* Chat (free to chat)
*/
chat,
/**
* Unavailable (offline)
*/
unavailable,
/**
* Unknown
*/
unknown
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.database.DbConnectionManager;
import java.sql.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
/**
* Representation of an entire roster associated with a registration id.
*
* @author Daniel Henninger
*/
public class PseudoRoster {
private static final String GET_ALL_USER_ROSTER_ITEMS =
"SELECT username FROM gatewayPseudoRoster WHERE registrationID=?";
private static final String REMOVE_ROSTER_ITEM =
"DELETE FROM gatewayPseudoRoster WHERE registrationID=? AND username=?";
private long registrationID;
private ConcurrentHashMap<String,PseudoRosterItem> pseudoRosterItems = new ConcurrentHashMap<String,PseudoRosterItem>();
/**
* Loads an existing pseudo roster.
*
* @param registrationID The ID of the registration the roster item is assocaited with.
*/
public PseudoRoster(long registrationID) {
this.registrationID = registrationID;
loadFromDb();
}
/**
* Returns the unique ID of the registration associated with the roster.
*
* @return the registration ID.
*/
public long getRegistrationID() {
return registrationID;
}
/**
* Returns the list of roster items associated with this registration ID.
*
* @return Map of roster item usernames to PseudoRosterItems.
*/
public ConcurrentHashMap<String,PseudoRosterItem> getRosterItems() {
return pseudoRosterItems;
}
/**
* Returns a set of just the usernames of contacts from this roster.
*
* @return Set of usernames.
*/
public Set<String> getContacts() {
return pseudoRosterItems.keySet();
}
/**
* Returns true or false if a pseudo roster item exists for a username.
*
* @param username Username to locate.
* @return Whether a roster item exists with the username.
*/
public Boolean hasItem(String username) {
return pseudoRosterItems.containsKey(username);
}
/**
* Retrieves a pseudo roster item for a username.
*
* @param username Username to locate.
* @return A PseudoRosterItem for the user specified.
*/
public PseudoRosterItem getItem(String username) {
return pseudoRosterItems.get(username);
}
/**
* Removes a pseudo roster item for a username.
*
* @param username Username to remove.
*/
public void removeItem(String username) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(REMOVE_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Creates a new pseudo roster item for a username, nickname, and list of groups.
*
* @param username Username to add.
* @param nickname Nickname for roster item.
* @param groups List of groups for roster item.
*/
public PseudoRosterItem createItem(String username, String nickname, String groups) {
PseudoRosterItem rosterItem = new PseudoRosterItem(registrationID, username, nickname, groups);
pseudoRosterItems.put(username, rosterItem);
return rosterItem;
}
/**
* Load pseudo roster from database.
*/
private void loadFromDb() {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(GET_ALL_USER_ROSTER_ITEMS);
pstmt.setLong(1, registrationID);
rs = pstmt.executeQuery();
while (rs.next()) {
String username = rs.getString(1);
try {
pseudoRosterItems.put(username, new PseudoRosterItem(registrationID, username));
}
catch (NotFoundException e) {
Log.error("Could not find pseudo roster item after already having found it.", e);
}
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.database.DbConnectionManager;
import java.sql.*;
/**
* Representation of a pseudo roster item.
*
* This is used for tracking information about a contact that we can't track on the legacy system itself.
*
* @author Daniel Henninger
*/
public class PseudoRosterItem {
private static final String INSERT_ROSTER_ITEM =
"INSERT INTO gatewayPseudoRoster(registrationID, username, nickname, groups) VALUES (?,?,?,?)";
private static final String LOAD_ROSTER_ITEM =
"SELECT nickname, groups FROM gatewayPseudoRoster WHERE registrationID=? AND username=?";
private static final String CHANGE_USERNAME =
"UPDATE gatewayPseudoRoster SET username=? WHERE registrationID=? AND username=?";
private static final String SET_NICKNAME =
"UPDATE gatewayPseudoRoster SET nickname=? WHERE registrationID=? AND username=?";
private static final String SET_GROUPS =
"UPDATE gatewayPseudoRoster SET groups=? WHERE registrationID=? AND username=?";
private static final String REMOVE_ROSTER_ITEM =
"DELETE FROM gatewayPseudoRoster WHERE registrationID=? AND username=?";
private long registrationID;
private String username;
private String nickname;
private String groups;
/**
* Creates a new roster item associated with a registration id.
*
* @param registrationID Id of the registration this roster item is associated with.
* @param username The username of the roster item.
* @param nickname The nickname associated with the roster item (may be null).
* @param groups The group list associated wit the roster item (may be null).
*/
public PseudoRosterItem(Long registrationID, String username, String nickname, String groups) {
if (registrationID == null || username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
this.registrationID = registrationID;
this.username = username;
this.nickname = nickname;
this.groups = groups;
try {
// Clean up potentially already existing item.
removeFromDb();
try {
// Insert new roster item.
insertIntoDb();
}
catch (Exception e) {
Log.error(e);
}
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Loads an existing roster item.
*
* @param registrationID The ID of the registration the roster item is assocaited with.
* @param username The username of the roster item.
* @throws org.jivesoftware.util.NotFoundException if the registration could not be loaded.
*/
public PseudoRosterItem(long registrationID, String username)
throws NotFoundException
{
this.registrationID = registrationID;
this.username = username;
loadFromDb();
}
/**
* Returns the unique ID of the registration associated with the roster item.
*
* @return the registration ID.
*/
public long getRegistrationID() {
return registrationID;
}
/**
* Returns the username associated with the roster item.
*
* @return the username.
*/
public String getUsername() {
return username;
}
/**
* Returns the nickname associated with the roster item.
*
* @return the nickname.
*/
public String getNickname() {
return nickname;
}
/**
* Returns the groups associated with the roster item.
*
* @return the groups.
*/
public String getGroups() {
return groups;
}
/**
* Changes the username of the roster item.
* @param username New username.
*/
public void changeUsername(String username) {
if (username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(CHANGE_USERNAME);
pstmt.setString(1, username);
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
this.username = username;
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the nickname for the roster item.
* @param nickname New nickname to be associated.
*/
public void setNickname(String nickname) {
this.nickname = nickname;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_NICKNAME);
if (nickname != null) {
pstmt.setString(1, nickname);
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the groups for the roster item.
* @param groups New group list to be associated.
*/
public void setGroups(String groups) {
this.groups = groups;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_GROUPS);
if (groups != null) {
pstmt.setString(1, groups);
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.setString(3, this.username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
public String toString() {
return username + ", " + nickname + ", " + groups;
}
/**
* Inserts a new roster item into the database.
*
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
private void insertIntoDb() throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(INSERT_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
if (nickname != null) {
pstmt.setString(3, nickname);
}
else {
pstmt.setNull(3, Types.VARCHAR);
}
if (groups != null) {
pstmt.setString(4, groups);
}
else {
pstmt.setNull(4, Types.VARCHAR);
}
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
/**
* Removeds a roster item from the database.
*
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
private void removeFromDb() throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(REMOVE_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
private void loadFromDb() throws NotFoundException {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_ROSTER_ITEM);
pstmt.setLong(1, registrationID);
pstmt.setString(2, username);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new NotFoundException("Pseudo roster item not found: " + registrationID + "/" + username);
}
this.nickname = rs.getString(1);
this.groups = rs.getString(2);
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.database.DbConnectionManager;
import java.util.Collection;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.PreparedStatement;
/**
* Handles retrieving pseudo rosters and other related tasks.
*
* @author Daniel Henninger
*/
public class PseudoRosterManager {
private static final String REMOVE_ROSTER =
"DELETE FROM gatewayPseudoRoster WHERE registrationID=?";
/**
* Manages registration information.
* @see org.jivesoftware.openfire.gateway.RegistrationManager
*/
public final RegistrationManager registrationManager = new RegistrationManager();
/**
* Retrieves a pseudo roster based off of a registration ID.
*
* @param registrationID To retrieve the roster for.
* @return A Pseudo roster
*/
public PseudoRoster getPseudoRoster(Long registrationID) {
return new PseudoRoster(registrationID);
}
/**
* Retrieves a pseudo roster based off of a registration.
*
* @param registration To retrieve the roster for.
* @return A Pseudo roster
*/
public PseudoRoster getPseudoRoster(Registration registration) {
return getPseudoRoster(registration.getRegistrationID());
}
/**
* Retrieves a pseudo roster based off of a registration.
*
* @param jid To retrieve the roster for.
* @param type TransportType the roster is for.
* @return A Pseudo roster
* @throws UserNotFoundException if the user is not actually registered.
*/
public PseudoRoster getPseudoRoster(JID jid, TransportType type) throws UserNotFoundException {
Collection<Registration> registrations = registrationManager.getRegistrations(jid, type);
if (registrations.isEmpty()) {
// User is not registered with us.
throw new UserNotFoundException("Unable to find registration.");
}
Registration registration = registrations.iterator().next();
return getPseudoRoster(registration);
}
/**
* Removes a pseudo roster entirely.
*
* @param registrationID ID to be removed.
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
public void removePseudoRoster(Long registrationID) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(REMOVE_ROSTER);
pstmt.setLong(1, registrationID);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.jivesoftware.openfire.auth.AuthFactory;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.util.Log;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.JiveID;
import org.jivesoftware.database.SequenceManager;
import java.util.Date;
import java.sql.*;
/**
* Contains information about the registration a user has made with an external transport.
* Each registration includes a username and password used to login to the transport
* as well as a registration date and last login date.<p>
*
* The password for the transport registration is stored in encrypted form using
* the Openfire password encryption key. See {@link AuthFactory#encryptPassword(String)}.
*
* @author Matt Tucker
*/
@JiveID(125)
public class Registration {
private static final String INSERT_REGISTRATION =
"INSERT INTO gatewayRegistration(registrationID, jid, transportType, " +
"username, password, nickname, registrationDate) VALUES (?,?,?,?,?,?,?)";
private static final String LOAD_REGISTRATION =
"SELECT jid, transportType, username, password, nickname, registrationDate, lastLogin " +
"FROM gatewayRegistration WHERE registrationID=?";
private static final String SET_LAST_LOGIN =
"UPDATE gatewayRegistration SET lastLogin=? WHERE registrationID=?";
private static final String SET_PASSWORD =
"UPDATE gatewayRegistration SET password=? WHERE registrationID=?";
private static final String SET_USERNAME =
"UPDATE gatewayRegistration SET username=? WHERE registrationID=?";
private static final String SET_NICKNAME =
"UPDATE gatewayRegistration SET nickname=? WHERE registrationID=?";
private long registrationID;
private JID jid;
private TransportType transportType;
private String username;
private String password;
private String nickname;
private Date registrationDate;
private Date lastLogin;
private boolean disconnectedMode = false;
/**
* Creates a new registration.
*
* @param jid the JID of the user making the registration.
* @param transportType the type of the transport.
* @param username the username on the transport.
* @param password the password on the transport.
* @param nickname the nickname on the transport.
*/
public Registration(JID jid, TransportType transportType, String username, String password, String nickname) {
if (jid == null || transportType == null || username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
// Ensure that we store the bare JID.
this.jid = new JID(jid.toBareJID());
this.transportType = transportType;
this.username = username;
this.password = password;
this.nickname = nickname;
this.registrationDate = new Date();
try {
insertIntoDb();
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Creates a new registration in disconnected (test) mode.
*
* Passing false for disconnectedMode is the same as the previous constructor.
*
* @param jid the JID of the user making the registration.
* @param transportType the type of the transport.
* @param username the username on the transport.
* @param password the password on the transport.
* @param nickname the nickname on the transport.
* @param disconnectedMode True or false if we are in disconnected mode.
*/
public Registration(JID jid, TransportType transportType, String username, String password, String nickname, Boolean disconnectedMode) {
if (jid == null || transportType == null || username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
this.disconnectedMode = disconnectedMode;
// Ensure that we store the bare JID.
this.jid = new JID(jid.toBareJID());
this.transportType = transportType;
this.username = username;
this.password = password;
this.nickname = nickname;
this.registrationDate = new Date();
try {
insertIntoDb();
}
catch (Exception e) {
Log.error(e);
}
}
/**
* Loads an existing registration.
*
* @param registrationID the ID of the registration.
* @throws NotFoundException if the registration could not be loaded.
*/
public Registration(long registrationID)
throws NotFoundException
{
this.registrationID = registrationID;
loadFromDb();
}
/**
* Returns the unique ID of the registration.
*
* @return the registration ID.
*/
public long getRegistrationID() {
return registrationID;
}
/**
* Returns the JID of the user that made this registration.
*
* @return the JID of the user.
*/
public JID getJID() {
return jid;
}
/**
* Returns the type of the transport.
*
* @return the transport type.
*/
public TransportType getTransportType() {
return transportType;
}
/**
* Returns the username used for logging in to the transport.
*
* @return the username.
*/
public String getUsername() {
return username;
}
/**
* Returns the password used for logging in to the transport.
*
* @return the password.
*/
public String getPassword() {
return password;
}
/**
* Returns the nickname used for logging in to the transport.
*
* @return the nickname.
*/
public String getNickname() {
return nickname;
}
/**
* Sets the password used for logging in to the transport.
*
* @param password new password for registration.
*/
public void setPassword(String password) {
this.password = password;
if (disconnectedMode) { return; }
// The password is stored in encrypted form for improved security.
String encryptedPassword = AuthFactory.encryptPassword(password);
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_PASSWORD);
if (password != null) {
pstmt.setString(1, encryptedPassword);
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the username used for logging in to the transport.
*
* @param username New username for transport registration.
*/
public void setUsername(String username) {
if (username == null) {
throw new NullPointerException("Arguments cannot be null.");
}
this.username = username;
if (disconnectedMode) { return; }
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_USERNAME);
pstmt.setString(1, username);
pstmt.setLong(2, registrationID);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Sets the nickname used for logging in to the transport.
*
* @param nickname New nickname for transport registration.
*/
public void setNickname(String nickname) {
this.nickname = nickname;
if (disconnectedMode) { return; }
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_NICKNAME);
if (nickname != null) {
pstmt.setString(1, nickname);
}
else {
pstmt.setNull(1, Types.VARCHAR);
}
pstmt.setLong(2, registrationID);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Returns the date that this transport registration was created.
*
* @return the date the registration was created.
*/
public Date getRegistrationDate() {
return registrationDate;
}
/**
* Returns the date that the user last logged in to the transport using this
* registration data, or <tt>null</tt> if the user has never logged in.
*
* @return the last login date.
*/
public Date getLastLogin() {
return lastLogin;
}
/**
* Sets the data that the user last logged into the transport.
*
* @param lastLogin the last login date.
*/
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
if (disconnectedMode) { return; }
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(SET_LAST_LOGIN);
pstmt.setLong(1, lastLogin.getTime());
pstmt.setLong(2, registrationID);
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
public String toString() {
return jid + ", " + transportType + ", " + username;
}
/**
* Inserts a new registration into the database.
*
* @throws SQLException if the SQL statement is wrong for whatever reason.
*/
private void insertIntoDb() throws SQLException {
if (disconnectedMode) { return; }
this.registrationID = SequenceManager.nextID(this);
Connection con = null;
PreparedStatement pstmt = null;
boolean abortTransaction = false;
try {
con = DbConnectionManager.getTransactionConnection();
pstmt = con.prepareStatement(INSERT_REGISTRATION);
pstmt.setLong(1, registrationID);
pstmt.setString(2, jid.toString());
pstmt.setString(3, transportType.name());
pstmt.setString(4, username);
if (password != null) {
// The password is stored in encrypted form for improved security.
String encryptedPassword = AuthFactory.encryptPassword(password);
pstmt.setString(5, encryptedPassword);
}
else {
pstmt.setNull(5, Types.VARCHAR);
}
if (nickname != null) {
pstmt.setString(6, nickname);
}
else {
pstmt.setNull(6, Types.VARCHAR);
}
pstmt.setLong(7, registrationDate.getTime());
pstmt.executeUpdate();
}
catch (SQLException sqle) {
abortTransaction = true;
throw sqle;
}
finally {
DbConnectionManager.closeTransactionConnection(pstmt, con, abortTransaction);
}
}
/**
* Load registration from database.
*
* @throws NotFoundException if registration was not found in database.
*/
private void loadFromDb() throws NotFoundException {
if (disconnectedMode) { return; }
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_REGISTRATION);
pstmt.setLong(1, registrationID);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new NotFoundException("Registration not found: " + registrationID);
}
this.jid = new JID(rs.getString(1));
this.transportType = TransportType.valueOf(rs.getString(2));
this.username = rs.getString(3);
// The password is stored in encrypted form, so decrypt it.
this.password = AuthFactory.decryptPassword(rs.getString(4));
this.nickname = rs.getString(5);
this.registrationDate = new Date(rs.getLong(6));
long loginDate = rs.getLong(7);
if (rs.wasNull()) {
this.lastLogin = null;
}
else {
this.lastLogin = new Date(loginDate);
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.NotFoundException;
import org.picocontainer.Startable;
import java.util.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
/**
* Manages registration data for transports. Individual transports use the registration data
* and then create sessions used to exchange messages and presence data.
*
* @author Matt Tucker
*/
public class RegistrationManager implements Startable {
private static final String DELETE_REGISTRATION =
"DELETE FROM gatewayRegistration WHERE registrationID=?";
private static final String ALL_REGISTRATION_COUNT =
"SELECT count(*) FROM gatewayRegistration";
private static final String ALL_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration ORDER BY jid,transportType";
private static final String LOAD_REGISTRATION =
"SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=? AND username=?";
private static final String ALL_USER_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE jid=? ORDER BY transportType";
private static final String ALL_GATEWAY_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE transportType=? ORDER BY jid";
private static final String USER_GATEWAY_REGISTRATIONS =
"SELECT registrationID FROM gatewayRegistration WHERE jid=? AND transportType=?";
private static final String DELETE_PSEUDO_ROSTER =
"DELETE FROM gatewayPseudoRoster WHERE registrationID=?";
public void start() {
}
public void stop() {
}
/**
* Creates a new registration.
*
* @param jid the JID of the user making the registration.
* @param transportType the type of the transport.
* @param username the username on the transport service.
* @param password the password on the transport service.
* @param nickname the nickname on the transport service.
* @return a new registration.
*/
public Registration createRegistration(JID jid, TransportType transportType, String username,
String password, String nickname)
{
return new Registration(jid, transportType, username, password, nickname);
}
/**
* Deletes a registration.
*
* @param registration the registration to delete.
*/
public void deleteRegistration(Registration registration) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(DELETE_REGISTRATION);
pstmt.setLong(1, registration.getRegistrationID());
pstmt.executeUpdate();
pstmt = con.prepareStatement(DELETE_PSEUDO_ROSTER);
pstmt.setLong(1, registration.getRegistrationID());
pstmt.executeUpdate();
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(pstmt, con);
}
}
/**
* Returns all registrations for a particular type of transport.
*
* @param transportType the transport type.
* @return all registrations for the transport type.
*/
public Collection<Registration> getRegistrations(TransportType transportType) {
List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_GATEWAY_REGISTRATIONS);
pstmt.setString(1, transportType.name());
rs = pstmt.executeQuery();
while (rs.next()) {
registrationIDs.add(rs.getLong(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
if (registrationIDs.isEmpty()) {
return Collections.emptyList();
}
else {
return new RegistrationCollection(registrationIDs);
}
}
/**
* Returns all registrations for a particular JID.
*
* @param jid the JID of the user.
* @return all registrations for the JID.
*/
public Collection<Registration> getRegistrations(JID jid) {
List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_USER_REGISTRATIONS);
// Use the bare JID of the user.
pstmt.setString(1, jid.toBareJID());
rs = pstmt.executeQuery();
while (rs.next()) {
registrationIDs.add(rs.getLong(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
if (registrationIDs.isEmpty()) {
return Collections.emptyList();
}
else {
return new RegistrationCollection(registrationIDs);
}
}
/**
* Returns all registrations that a JID has on a particular transport type.
* In the typical case, a JID has a single registration with a particular transport
* type. However, it's also possible to maintain multiple registrations. For example,
* the user "joe_smith@example.com" might have have two user accounts on the AIM
* transport service: "jsmith" and "joesmith".
*
* @param jid the JID of the user.
* @param transportType the type of the transport.
* @return all registrations for the JID of a particular transport type.
*/
public Collection<Registration> getRegistrations(JID jid, TransportType transportType) {
List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(USER_GATEWAY_REGISTRATIONS);
// Use the bare JID of the user.
pstmt.setString(1, jid.toBareJID());
pstmt.setString(2, transportType.name());
rs = pstmt.executeQuery();
while (rs.next()) {
registrationIDs.add(rs.getLong(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
if (registrationIDs.isEmpty()) {
return Collections.emptyList();
}
else {
return new RegistrationCollection(registrationIDs);
}
}
/**
* Returns a registration given a JID, transport type, and username.
*
* @param jid the JID of the user.
* @param transportType the transport type.
* @param username the username on the transport service.
* @return the registration.
* @throws NotFoundException if the registration could not be found.
*/
public Registration getRegistration(JID jid, TransportType transportType, String username)
throws NotFoundException
{
long registrationID = -1;
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(LOAD_REGISTRATION);
pstmt.setString(1, jid.toBareJID());
pstmt.setString(2, transportType.name());
pstmt.setString(3, username);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new NotFoundException("Could not load registration with ID " + registrationID);
}
registrationID = rs.getLong(1);
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return new Registration(registrationID);
}
/**
* Returns the count of all registrations.
*
* @return the total count of registrations.
*/
public int getRegistrationCount() {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_REGISTRATION_COUNT);
rs = pstmt.executeQuery();
rs.next();
return rs.getInt(1);
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
return 0;
}
/**
* Returns all registrations.
*
* @return all registrations.
*/
public Collection<Registration> getRegistrations() {
List<Long> registrationIDs = new ArrayList<Long>();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(ALL_REGISTRATIONS);
rs = pstmt.executeQuery();
while (rs.next()) {
registrationIDs.add(rs.getLong(1));
}
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
DbConnectionManager.closeConnection(rs, pstmt, con);
}
if (registrationIDs.isEmpty()) {
return Collections.emptyList();
}
else {
return new RegistrationCollection(registrationIDs);
}
}
/**
* Converts a list of registration IDs into a Collection of Registrations.
*/
private class RegistrationCollection extends AbstractCollection {
private List<Long> registrationIDs;
/**
* Constructs a new query results object.
*
* @param registrationIDs the list of registration IDs.
*/
public RegistrationCollection(List<Long> registrationIDs) {
this.registrationIDs = registrationIDs;
}
public Iterator iterator() {
final Iterator<Long> regIterator = registrationIDs.iterator();
return new Iterator() {
private Object nextElement = null;
public boolean hasNext() {
if (nextElement == null) {
nextElement = getNextElement();
if (nextElement == null) {
return false;
}
}
return true;
}
public Object next() {
Object element;
if (nextElement != null) {
element = nextElement;
nextElement = null;
}
else {
element = getNextElement();
if (element == null) {
throw new NoSuchElementException();
}
}
return element;
}
public void remove() {
throw new UnsupportedOperationException();
}
private Object getNextElement() {
if (!regIterator.hasNext()) {
return null;
}
while (regIterator.hasNext()) {
try {
long registrationID = regIterator.next();
return new Registration(registrationID);
}
catch (Exception e) {
Log.error(e);
}
}
return null;
}
};
}
public int size() {
return registrationIDs.size();
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* An enumeration for supported features.
*
* This represents features that the client supports that we have detected and
* can make use of.
*
* @author Daniel Henninger
*/
public enum SupportedFeature {
/**
* Chat States (XEP-0085)
*/
chatstates
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* Transport Buddy.
*
* This is simply a means for providing a collection of information about
* a legacy service (transport) buddy to the underlying system. It collects
* all of the necessary pieces into one object.
*
* @author Daniel Henninger
*/
public class TransportBuddy {
/**
* Creates a TransportBuddy instance.
*
* @param contactname The legacy contact name.
* @param nickname The legacy nickname (can be null).
* @param group The group the legacy contact is in (can be null).
*/
public TransportBuddy(String contactname, String nickname, String group) {
this.contactname = contactname.toLowerCase();
this.nickname = nickname;
this.group = group;
}
/**
* ID, Screenname, name, whatever the contact name is on the legacy system
*/
public String contactname = null;
/**
* A nickname associated with this contact, if it exists.
*/
public String nickname = null;
/**
* A group associated with this contact, if it exists.
*/
public String group = null;
/**
* Retrieves the name of the contact.
*
* @return Name of contact.
*/
public String getName() {
return contactname;
}
/**
* Retrieves the nickname of the contact.
*
* @return Nickname of contact.
*/
public String getNickname() {
return nickname;
}
/**
* Retrieves the group of the contact.
*
* @return Group contact is in.
*/
public String getGroup() {
return group;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.xmpp.component.ComponentManager;
import java.util.Map;
/**
* Transport Instance
*
* Represents all information that needs to be tracked about a gateway instance.
*
* @author Daniel Henninger
*/
public class TransportInstance implements PropertyEventListener {
private ComponentManager componentManager;
private String description = null;
private String nameOfClass = null;
public BaseTransport transport = null;
private TransportType type = null;
private Boolean enabled = false;
private Boolean running = false;
private String subDomain;
/**
* Creates a new transport instance.
*
* @param type Type of transport.
* @param description Short description of transport.
* @param classname Full name/path of class associated with instance.
* @param componentManager Component manager managing this instance.
*/
public TransportInstance(TransportType type, String description, String classname, ComponentManager componentManager) {
this.description = description;
this.type = type;
this.nameOfClass = classname;
this.componentManager = componentManager;
enabled = JiveGlobals.getBooleanProperty("plugin.gateway."+this.type.toString()+".enabled", false);
subDomain = JiveGlobals.getProperty("plugin.gateway."+this.type.toString()+".subdomain", this.type.toString());
}
/**
* Retrieves the name of the service (aka, subdomain)
*
* @return name of the service
*/
public String getName() {
return this.type.toString();
}
/**
* Returns whether this transport instance is enabled.
*
* @return true or false if instance is enabled
*/
public Boolean isEnabled() {
return enabled;
}
/**
* Returns whether this transport instance is currently running.
*
* @return true or false if instance is currently running
*/
public Boolean isRunning() {
return running;
}
/**
* Enables the transport instance and starts it if it's not already running.
*/
public void enable() {
enabled = true;
JiveGlobals.setProperty("plugin.gateway."+this.type.toString()+".enabled", "true");
if (!running) {
startInstance();
}
}
/**
* Disables the transport instance and stops it if it's running.
*/
public void disable() {
enabled = false;
JiveGlobals.setProperty("plugin.gateway."+this.type.toString()+".enabled", "false");
if (running) {
stopInstance();
}
}
/**
* Starts the transport instance if it's enabled and not already running.
*/
public void startInstance() {
if (!enabled || running) {
return;
}
Log.info("Starting transport service: "+type.toString());
transport = null;
//Log.debug("Loading class "+nameOfClass);
try {
transport = (BaseTransport)Class.forName(nameOfClass).newInstance();
transport.setup(this.type, this.description);
}
catch (ClassNotFoundException e) {
Log.error("Unable to find class: "+nameOfClass);
}
catch (InstantiationException e) {
Log.error("Unable to instantiate class: "+nameOfClass);
}
catch (IllegalAccessException e) {
Log.error("Unable to access class: "+nameOfClass);
}
try {
componentManager.addComponent(this.subDomain, transport);
PropertyEventDispatcher.addListener(this);
running = true;
}
catch (Exception e) {
componentManager.getLog().error(e);
}
}
/**
* Stops the transport instance if it's running.
*/
public void stopInstance() {
if (!running) {
return;
}
Log.info("Stopping transport service: "+type.toString());
PropertyEventDispatcher.removeListener(this);
try {
componentManager.removeComponent(this.subDomain);
}
catch (Exception e) {
componentManager.getLog().error(e);
}
transport = null;
running = false;
}
/**
* Retrieves actual transport associated with this instance.
*
* @return Transport that the instance is associated with.
*/
public BaseTransport getTransport() {
return transport;
}
public void propertySet(String property, Map params) {
if (property.startsWith("plugin.gateway.")) {
if (property.equals("plugin.gateway."+this.type.toString()+".enabled")) {
enabled = Boolean.parseBoolean((String)params.get("value"));
if (enabled) {
if (!running) {
startInstance();
}
}
else {
if (running) {
stopInstance();
}
}
}
else if (property.equals("plugin.gateway."+this.type.toString()+".subdomain")) {
String newSubDomain = (String)params.get("value");
if (!newSubDomain.equals(this.subDomain)) {
if (running) {
stopInstance();
this.subDomain = newSubDomain;
startInstance();
}
}
}
}
}
public void propertyDeleted(String property, Map params) {
if (property.startsWith("plugin.gateway.")) {
if (property.equals("plugin.gateway."+this.type.toString()+".enabled")) {
if (running) {
stopInstance();
}
}
else if (property.equals("plugin.gateway."+this.type.toString()+".subdomain")) {
String newSubDomain = this.type.toString();
if (!newSubDomain.equals(this.subDomain)) {
if (running) {
stopInstance();
this.subDomain = newSubDomain;
startInstance();
}
}
}
}
}
public void xmlPropertySet(String property, Map params) {
propertySet(property, params);
}
public void xmlPropertyDeleted(String property, Map params) {
propertyDeleted(property, params);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* An enumeration for different login statuses.
*
* This represents a progression of login statuses to a legacy network.
*
* @author Daniel Henninger
*/
public enum TransportLoginStatus {
/**
* Not logged in - not logged into the remote service at all
*/
LOGGED_OUT,
/**
* Currently logging in - in the process of logging into the remote service
*/
LOGGING_IN,
/**
* Logged in - active session that should be completely functional
*/
LOGGED_IN,
/**
* Logging out - in the process of logging out of the remote service
*/
LOGGING_OUT,
/**
* Disconnected - automatically disconnected for some reason, similar to LOGGED_OUT
*/
DISCONNECTED,
/**
* Reconnecting - in the process of automatically reconnecting, similar to LOGGING_IN
*/
RECONNECTING
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.session.ClientSession;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
/**
* Interface for a transport session.
*
* This outlines all of the functionality that is required for a transport
* to implement. These are functions that the XMPP side of things are going
* interact with. The legacy transport itself is expected to handle messages
* going to the Jabber user.
*
* @author Daniel Henninger
*/
public abstract class TransportSession implements Runnable {
/**
* Creates a TransportSession instance.
*
* @param registration Registration this session is associated with.
* @param jid JID of user associated with this session.
* @param transport Transport this session is associated with.
*/
public TransportSession(Registration registration, JID jid, BaseTransport transport) {
this.jid = new JID(jid.toBareJID());
this.registration = registration;
this.transport = transport;
Log.debug("Created "+transport.getType()+" session for "+jid+" as '"+registration.getUsername()+"'");
}
/**
* Convenience constructor that includes priority.
*
* @param registration Registration this session is associated with.
* @param jid JID of user associated with this session.
* @param transport Transport this session is associated with.
* @param priority Priority associated with session.
*/
public TransportSession(Registration registration, JID jid, BaseTransport transport, Integer priority) {
this.jid = new JID(jid.toBareJID());
this.registration = registration;
this.transport = transport;
addResource(jid.getResource(), priority);
Log.debug("Created "+transport.getType()+" session for "+jid+" as '"+registration.getUsername()+"'");
}
/**
* Registration that this session is associated with.
*/
public Registration registration;
/**
* Transport this session is associated with.
*/
public BaseTransport transport;
/**
* The bare JID the session is associated with.
*/
public JID jid;
/**
* All JIDs (including resources) that are associated with this session.
*/
public ConcurrentHashMap<String,Integer> resources = new ConcurrentHashMap<String,Integer>();
/**
* Current highest resource.
*/
public String highestResource = null;
/**
* Is this session valid? Set to false when session is done.
*/
public boolean validSession = true;
/**
* Is the roster locked for sync editing?
*/
public boolean rosterLocked = false;
/**
* Contains a list of specific roster items that are locked.
*/
public ArrayList<String> rosterItemsLocked = new ArrayList<String>();
/**
* The current login status on the legacy network.
*/
public TransportLoginStatus loginStatus = TransportLoginStatus.LOGGED_OUT;
/**
* Supported features.
*/
public ArrayList<SupportedFeature> supportedFeatures = new ArrayList<SupportedFeature>();
/**
* Number of reconnection attempts made.
*/
public Integer reconnectionAttempts = 0;
/**
* Associates a resource with the session, and tracks it's priority.
*
* @param resource Resource string
* @param priority Priority of resource
*/
public void addResource(String resource, Integer priority) {
resources.put(resource, priority);
if (highestResource == null || resources.get(highestResource) >= priority) {
highestResource = resource;
}
}
/**
* Removes an association of a resource with the session.
*
* @param resource Resource string
*/
public void removeResource(String resource) {
resources.remove(resource);
try {
getTransport().notifyRosterOffline(new JID(getJID().getNode(),getJID().getDomain(),resource));
}
catch (UserNotFoundException e) {
// Don't care
}
if (resource.equals(highestResource)) {
Integer highestPriority = -255;
String tmpHighestResource = null;
for (String res : resources.keySet()) {
if (resources.get(res) > highestPriority) {
tmpHighestResource = res;
highestPriority = resources.get(res);
}
}
highestResource = tmpHighestResource;
}
}
/**
* Updates the priority of a resource.
*
* @param resource Resource string
* @param priority New priority
*/
public void updateResource(String resource, Integer priority) {
resources.put(resource, priority);
Integer highestPriority = -255;
String tmpHighestResource = null;
for (String res : resources.keySet()) {
if (resources.get(res) > highestPriority) {
tmpHighestResource = res;
highestPriority = resources.get(res);
}
}
highestResource = tmpHighestResource;
}
/**
* Removes all resources associated with a session.
*/
public void removeAllResources() {
for (String resource : resources.keySet()) {
removeResource(resource);
}
}
/**
* Returns the number of active resources.
*
* @return Number of active resources.
*/
public int getResourceCount() {
return resources.size();
}
/**
* Returns if the roster is currently locked.
*
* @return true or false if the roster is locked.
*/
public boolean isRosterLocked() {
return rosterLocked;
}
/**
* Returns if a specific roster item is currently locked.
*
* Also checks global lock.
*
* @param jid JID to check whether it's locked.
* @return true or false if the roster item is locked.
*/
public boolean isRosterLocked(String jid) {
return rosterLocked || rosterItemsLocked.contains(jid);
}
/**
* Locks the roster (typically used for editing during syncing).
*/
public void lockRoster() {
rosterLocked = true;
}
/**
* Locks a specific roster item (typically used for direct roster item updates).
*
* @param jid JID to lock.
*/
public void lockRoster(String jid) {
if (!rosterItemsLocked.contains(jid)) {
rosterItemsLocked.add(jid);
}
}
/**
* Unlocks the roster after sync editing is complete.
*/
public void unlockRoster() {
rosterLocked = false;
}
/**
* Unlocks a specific roster item.
*
* @param jid JID to unlock.
*/
public void unlockRoster(String jid) {
if (rosterItemsLocked.contains(jid)) {
rosterItemsLocked.remove(jid);
}
}
/**
* Retrieves the registration information associated with the session.
*
* @return Registration information of the user associated with the session.
*/
public Registration getRegistration() {
return registration;
}
/**
* Retrieves the transport associated with the session.
*
* @return Transport associated with the session.
*/
public BaseTransport getTransport() {
return transport;
}
/**
* Retrieves the roster associated with the session.
*
* @return Roster associated with the session, or null if none.
*/
public Roster getRoster() {
try {
return getTransport().getRosterManager().getRoster(getJID().getNode());
}
catch (UserNotFoundException e) {
return null;
}
}
/**
* Retrieves the bare jid associated with the session.
*
* @return JID of the user associated with this session.
*/
public JID getJID() {
return jid;
}
/**
* Retrieves the JID of the highest priority resource.
*
* @return Full JID including resource with highest priority.
*/
public JID getJIDWithHighestPriority() {
return new JID(jid.getNode(),jid.getDomain(),highestResource);
}
/**
* Given a resource, returns whether it's priority is the highest.
*
* @param resource Resource to be checked.
* @return True or false if the resource is the highest priority.
*/
public Boolean isHighestPriority(String resource) {
return (highestResource.equals(resource));
}
/**
* Change the priority of a given resource.
*
* @param resource Resource to be changed.
* @param priority New priority of resource
*/
public void updatePriority(String resource, Integer priority) {
updateResource(resource, priority);
// TODO: should potentially ask for status of highest priority
}
/**
* Retrieves the priority of a given resource.
*
* @param resource Resource to be checked.
* @return Priority of the resource, or null if not found.
*/
public Integer getPriority(String resource) {
return resources.get(resource);
}
/**
* Given a resource, returns whether the resource is currently associated with this session.
*
* @param resource Resource to be checked.
* @return True of false if the resource is associated with this session.
*/
public Boolean hasResource(String resource) {
return (resources.containsKey(resource));
}
/**
* Sets a feature that the client supports.
*
* @param feature Feature that the session supports.
*/
public void setSupportedFeature(SupportedFeature feature) {
if (!supportedFeatures.contains(feature)) {
supportedFeatures.add(feature);
}
}
/**
* Removes a feature that the client supports.
*
* @param feature Feature to be removed from the supported list.
*/
public void removeSupportedFeature(SupportedFeature feature) {
supportedFeatures.remove(feature);
}
/**
* Clears all of the supported features recorded.
*/
public void clearSupportedFeatures() {
supportedFeatures.clear();
}
/**
* Retrieves whether this session supports a specific feature.
*
* @param feature Feature to check for support of.
* @return True or false if the session supports the specified feature.
*/
public Boolean isFeatureSupported(SupportedFeature feature) {
return supportedFeatures.contains(feature);
}
/**
* Updates the login status.
*
* @param status New login status.
*/
public void setLoginStatus(TransportLoginStatus status) {
loginStatus = status;
if (status.equals(TransportLoginStatus.LOGGED_IN)) {
reconnectionAttempts = 0;
}
}
/**
* Retrieves the current login status.
*
* @return Login status of session.
*/
public TransportLoginStatus getLoginStatus() {
return loginStatus;
}
/**
* Returns true only if we are completely logged in.
*
* @return True or false whether we are currently completely logged in.
*/
public Boolean isLoggedIn() {
return (loginStatus == TransportLoginStatus.LOGGED_IN);
}
/**
* Handles monitoring of whether session is still valid.
*/
public void run() {
while (validSession) { }
}
/**
* Indicates that the session is done and should be stopped.
*/
public void sessionDone() {
validSession = false;
}
/**
* Should be called when a session has been disconnected.
*
* This can be anything from a standard logout to a forced disconnect from the server.
*/
public void sessionDisconnected() {
reconnectionAttempts++;
cleanUp();
if (reconnectionAttempts > JiveGlobals.getIntProperty("plugin.gateway."+getTransport().getType()+"reconnectattempts", 3)) {
sessionDisconnectedNoReconnect();
}
else {
setLoginStatus(TransportLoginStatus.RECONNECTING);
ClientSession session = XMPPServer.getInstance().getSessionManager().getSession(getJIDWithHighestPriority());
logIn(getTransport().getPresenceType(session.getPresence()), null);
}
}
/**
* Should be called when a session has been disconnected but no reconnect attempt should be made.
*
* It is also called internally by sessionDisconnected to handle total failed attempt.
*/
public void sessionDisconnectedNoReconnect() {
Log.debug("Disconnecting session "+getJID()+" from "+getTransport().getJID());
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
try {
getTransport().notifyRosterOffline(getJID());
}
catch (UserNotFoundException e) {
// Don't care
}
}
/**
* Updates status on legacy service.
*
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public abstract void updateStatus(PresenceType presenceType, String verboseStatus);
/**
* Adds a legacy contact to the legacy service.
*
* @param item Roster item associated with the legacy contact.
*/
public abstract void addContact(RosterItem item);
/**
* Removes a legacy contact from the legacy service.
*
* @param item Roster item associated with the legacy contact.
*/
public abstract void removeContact(RosterItem item);
/**
* Updates a legacy contact on the legacy service.
*
* @param item Roster item associated with the legacy contact.
*/
public abstract void updateContact(RosterItem item);
/**
* Sends an outgoing message through the legacy service.
*
* @param jid JID associated with the target contact.
* @param message Message to be sent.
*/
public abstract void sendMessage(JID jid, String message);
/**
* Sends an outgoing message directly to the legacy service.
*
* Doesn't -have- to do anything. Only occasionally useful.
*
* @param message Message to be sent.
*/
public abstract void sendServerMessage(String message);
/**
* Sends a chat state message through the legacy service.
*
* Not all chat states have to be handled. Note that composing message event
* is sent through this as well. (XEP-0022) Primarily this is used with XEP-0085.
*
* @param jid JID associated with the target contact.
* @param chatState Chat state to be reflected in the legacy service.
*/
public abstract void sendChatState(JID jid, ChatStateType chatState);
/**
* Asks the legacy service to send a presence packet for a contact.
*
* This is typically response to a probe.
*
* @param jid JID to be checked.
*/
public abstract void retrieveContactStatus(JID jid);
/**
* Asks the legacy service to send presence packets for all known contacts.
*
* @param jid JID to have the presence packets sent to.
*/
public abstract void resendContactStatuses(JID jid);
/**
* Should be called when the service is to be logged into.
*
* This is expected to check for current logged in status and log in if appropriate.
*
* @param presenceType Initial status (away, available, etc) to be set upon logging in.
* @param verboseStatus Descriptive status to be set upon logging in.
*/
public abstract void logIn(PresenceType presenceType, String verboseStatus);
/**
* Should be called when the service is to be disconnected from.
*
* This is expected to check for current logged in status and log out if appropriate.
*/
public abstract void logOut();
/**
* Clean up session pieces for either a log out or in preparation for a reconnection.
*/
public abstract void cleanUp();
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
import java.util.*;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.openfire.SessionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
/**
* Manages sessions with legacy transports implementations.
*
* Keeps track of all of the active sessions with the various transports.
* Only one expected to be associated with a single transport instance.
*
* @author Daniel Henninger
*/
public class TransportSessionManager {
/**
* Container for all active sessions.
*/
private Map<JID,TransportSession> activeSessions = new HashMap<JID,TransportSession>();
/**
* Timer to check for orphaned sessions.
*/
private Timer timer = new Timer();
/**
* Interval at which sessions are reaped.
*/
private int reaperInterval = 300000; // 5 minutes
/**
* The actual repear task.
*/
private SessionReaper sessionReaper;
/**
* The transport we are associated with.
*/
BaseTransport transport;
/**
* Group of all threads related to this session.
*/
public ThreadGroup threadGroup;
/**
* Creates the transport session manager instance and initializes.
*
* @param transport Transport associated with this session manager.
*/
TransportSessionManager(BaseTransport transport) {
this.transport = transport;
sessionReaper = new SessionReaper();
timer.schedule(sessionReaper, reaperInterval, reaperInterval);
}
/**
* Shuts down the session manager.
*/
public void shutdown() {
sessionReaper.cancel();
timer.cancel();
}
/**
* Initialize the thread group manager.
*
* @param jid JID for naming purposes of the thread group manager.
*/
public void startThreadManager(JID jid) {
threadGroup = new ThreadGroup(jid.toString());
}
/**
* Destroys the thread group manager.
*/
public void stopThreadManager() {
threadGroup.destroy();
}
/**
* Starts a thread associated with a session.
*
* @param session Session the thread will be associated with.
* @return A thread wrapped around the session.
*/
public Thread startThread(TransportSession session) {
// TODO: This does not work well. Disabling.
// Thread sessionThread = new Thread(threadGroup, session);
// sessionThread.start();
// return sessionThread;
return null;
}
/**
* Retrieve the session instance for a given JID.
*
* Ignores the resource part of the jid.
*
* @param jid JID of the instance to be retrieved.
* @throws NotFoundException if the given jid is not found.
* @return TransportSession instance requested.
*/
public TransportSession getSession(JID jid) throws NotFoundException {
TransportSession session = activeSessions.get(new JID(jid.toBareJID()));
if (session == null) {
throw new NotFoundException("Could not find session requested.");
}
return session;
}
/**
* retrieves the session instance for a given user.
*
* @param username Username of the instance to be retrieved.
* @throws NotFoundException if the given username is not found.
* @return TransportSession instance requested.
*/
public TransportSession getSession(String username) throws NotFoundException {
TransportSession session = activeSessions.get(XMPPServer.getInstance().createJID(username, null));
if (session == null) {
throw new NotFoundException("Could not find session requested.");
}
return session;
}
/**
* Stores a new session instance with the legacy service.
*
* Expects to be given a JID and a pre-created session. Ignores the
* resource part of the JID.
*
* @param jid JID information used to track the session.
* @param session TransportSession associated with the jid.
*/
public void storeSession(JID jid, TransportSession session) {
activeSessions.put(new JID(jid.toBareJID()), session);
}
/**
* Removes a session instance with the legacy service.
*
* Expects to be given a JID which indicates which session we are
* removing.
*
* @param jid JID to be removed.
*/
public void removeSession(JID jid) {
activeSessions.remove(new JID(jid.toBareJID()));
try {
getTransport().notifyRosterOffline(jid);
}
catch (UserNotFoundException e) {
// Don't care
}
}
/**
* Retrieves a collection of all active sessions.
*
* @return List of active sessions.
*/
public Collection<TransportSession> getSessions() {
return activeSessions.values();
}
/**
* Bury any transport sessions that no longer have an associated xmpp session.
*/
private class SessionReaper extends TimerTask {
/**
* Kill any session that has been orphaned.
*/
public void run() {
cleanupOrphanedSessions();
}
}
/**
* Compares active xmpp sessions with active transport sessions and buries the orphaned.
*/
private void cleanupOrphanedSessions() {
SessionManager sessionManager = SessionManager.getInstance();
for (TransportSession session : getSessions()) {
if (sessionManager.getSessionCount(session.getJID().getNode()) == 0) {
transport.registrationLoggedOut(session);
}
}
}
/**
* Retrieves the transport this session manager is associated with.
*
* @return transport associated with this session manager.
*/
public BaseTransport getTransport() {
return this.transport;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* An enumeration for the valid transport types, which encompasses proprietary IM networks
* as well as other IM protocols.
*
* @author Matt Tucker
*/
public enum TransportType {
/**
* The AOL instant messaging service.
*/
aim,
/**
* The ICQ instant messaging service.
*/
icq,
/**
* The Yahoo instant messaging service.
*/
yahoo,
/**
* The MSN instant messaging service.
*/
msn,
/**
* A gateway to a SIP/SIMPLE servers.
*/
sip,
/**
* A gateway to other XMPP servers.
*/
xmpp,
/**
* A gateway to Google Talk ('special' XMPP server)
*/
gtalk,
/**
* A gateway to IRC servers.
*/
irc,
/**
* A gateway to a service not covered by the other options..
*/
other
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway;
/**
* User Capabilities Tracking
*
* Some functionality in XMPP requires that you've already checked to see if the target XMPP
* user has indicated that they support the same functionality. This class is meant to help
* track a list of supported features that we care about, and any associated helpful information.
*
* @author Daniel Henninger
*/
public class UserCapabilities {
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.irc;
import org.schwering.irc.lib.IRCEventListener;
import org.schwering.irc.lib.IRCUser;
import org.schwering.irc.lib.IRCModeParser;
import org.schwering.irc.lib.IRCUtil;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.xmpp.packet.JID;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.PresenceType;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import java.util.*;
/**
* Handles listening for IRC events.
*
* @author Daniel Henninger
*/
public class IRCListener implements IRCEventListener {
public IRCListener(IRCSession session) {
this.session = session;
}
/**
* Timer to check for online status.
*/
public Timer timer = new Timer();
/**
* Interval at which status is checked.
*/
private int timerInterval = 60000; // 1 minute
/**
* Session this listener is associated with.
*/
IRCSession session;
/**
* Effectively enables or disables the listener functionality, without burying it yet.
*/
Boolean silenced = false;
/**
* Status checker.
*/
StatusCheck statusCheck;
/**
* Retrieves the session this listener is associated with.
*
* @return The session the listener is associated with.
*/
public IRCSession getSession() {
return session;
}
public void onRegistered() {
Log.debug("IRC registered");
getSession().getRegistration().setLastLogin(new Date());
Presence p = new Presence();
p.setFrom(getSession().getTransport().getJID());
p.setTo(getSession().getJID());
getSession().getTransport().sendPacket(p);
getSession().setLoginStatus(TransportLoginStatus.LOGGED_IN);
String buddyList = "";
for (String buddy : getSession().getBuddyStatuses().keySet()) {
buddyList = buddyList + " " + buddy;
}
if (!buddyList.equals("")) {
getSession().getConnection().doIson(buddyList);
}
statusCheck = new StatusCheck();
timer.schedule(statusCheck, timerInterval, timerInterval);
}
public void onDisconnected() {
Log.debug("IRC disconnected");
getSession().sessionDisconnected();
}
public void onError(String string) {
Log.debug("IRC error: "+string);
if (silenced) { return; }
getSession().getTransport().sendMessage(
getSession().getJID(),
getSession().getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.irc.errorreceived", "gateway")+" "+string,
Message.Type.error
);
}
public void onError(int i, String string) {
Log.debug("IRC error: "+i+", "+string);
if (silenced) { return; }
getSession().getTransport().sendMessage(
getSession().getJID(),
getSession().getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.irc.errorreceivedwithcode", "gateway", Arrays.asList(Integer.toString(i)))+" "+string,
Message.Type.error
);
}
public void onInvite(String string, IRCUser ircUser, String string1) {
Log.debug("IRC invite: "+string+", "+ircUser+", "+string1);
}
public void onJoin(String string, IRCUser ircUser) {
Log.debug("IRC join: "+string+", "+ircUser);
}
public void onKick(String string, IRCUser ircUser, String string1, String string2) {
Log.debug("IRC kick: "+string+", "+ircUser+", "+string1+", "+string2);
}
public void onMode(String string, IRCUser ircUser, IRCModeParser ircModeParser) {
Log.debug("IRC mode: "+string+", "+ircUser+", "+ircModeParser);
}
public void onMode(IRCUser ircUser, String string, String string1) {
Log.debug("IRC mode: "+ircUser+", "+string+", "+string1);
}
public void onNick(IRCUser ircUser, String string) {
Log.debug("IRC nick: "+ircUser+", "+string);
}
public void onNotice(String string, IRCUser ircUser, String string1) {
Log.debug("IRC notice: "+string+", "+ircUser+", "+string1);
if (silenced) { return; }
String username = ircUser.getNick();
if (username == null) {
username = ircUser.getUsername();
}
JID from;
if (username == null) {
from = getSession().getTransport().getJID();
}
else {
from = getSession().getTransport().convertIDToJID(username);
}
getSession().getTransport().sendMessage(
getSession().getJIDWithHighestPriority(),
from,
string1
);
}
public void onPart(String string, IRCUser ircUser, String string1) {
Log.debug("IRC part: "+string+", "+ircUser+", "+string1);
}
public void onPing(String string) {
// Nothing to do, handled automatically.
}
public void onPrivmsg(String chan, IRCUser ircUser, String msg) {
Log.debug("IRC privmsg: "+chan+", "+ircUser+", "+msg);
if (silenced) { return; }
if (msg.equals("VERSION")) {
// This is actually a CTCP VERSION request. Why is it showing as a Privmsg?
// TODO: Should figure out a proper way to handle this.
//getSession().getConnection().send("CTCP REPLY "+ircUser.getNick()+" VERSION IM Gateway Plugin for Openfire");
return;
}
getSession().getTransport().sendMessage(
getSession().getJIDWithHighestPriority(),
getSession().getTransport().convertIDToJID(ircUser.getNick()),
msg
);
}
public void onQuit(IRCUser ircUser, String string) {
Log.debug("IRC quit: "+ircUser+", "+string);
getSession().sessionDisconnectedNoReconnect();
}
public void onReply(int i, String string, String string1) {
Log.debug("IRC reply: "+i+", "+string+", "+string1);
if (silenced) { return; }
if (i == IRCUtil.RPL_ISON) {
String[] onlineContacts = string1.split(" ");
ArrayList<String> onlineContactList = new ArrayList<String>();
// Lets see who all is on
for (String contact : onlineContacts) {
onlineContactList.add(contact);
getSession().setBuddyStatus(contact, PresenceType.available);
}
// Now lets compare with who all is not on
for (String contact : getSession().getBuddyStatuses().keySet()) {
if (!onlineContactList.contains(contact)) {
getSession().setBuddyStatus(contact, PresenceType.unavailable);
}
}
}
else {
getSession().getTransport().sendMessage(
getSession().getJIDWithHighestPriority(),
getSession().getTransport().getJID(),
string1
);
}
}
public void onTopic(String string, IRCUser ircUser, String string1) {
Log.debug("IRC topic: "+string+", "+ircUser+", "+string1);
}
public void unknown(String string, String string1, String string2, String string3) {
Log.debug("Unknown IRC message: "+string+", "+string1+", "+string2+", "+string3);
}
public void setSilenced(Boolean setting) {
silenced = setting;
}
private class StatusCheck extends TimerTask {
/**
* Send ISON to IRC to check on status of contacts.
*/
public void run() {
String buddyList = "";
for (String buddy : getSession().getBuddyStatuses().keySet()) {
buddyList = buddyList + " " + buddy;
}
if (!buddyList.equals("")) {
getSession().getConnection().doIson(buddyList);
}
}
}
public Timer getTimer() {
return timer;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.irc;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.xmpp.packet.PacketError;
import org.schwering.irc.lib.IRCConnection;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents an IRC session.
*
* This is the interface with which the base transport functionality will
* communicate with IRC.
*
* @author Daniel Henninger
*/
public class IRCSession extends TransportSession {
final private PseudoRosterManager pseudoRosterManager = new PseudoRosterManager();
/**
* Create a MSN Session instance.
*
* @param registration Registration informationed used for logging in.
* @param jid JID associated with this session.
* @param transport Transport instance associated with this session.
* @param priority Priority of this session.
*/
public IRCSession(Registration registration, JID jid, IRCTransport transport, Integer priority) {
super(registration, jid, transport, priority);
pseudoRoster = pseudoRosterManager.getPseudoRoster(registration);
for (String contact : pseudoRoster.getContacts()) {
buddyStatuses.put(contact, PresenceType.unavailable);
}
String server = JiveGlobals.getProperty("plugin.gateway.irc.connecthost", "irc.freenode.net");
int[] ports = new int[] { JiveGlobals.getIntProperty("plugin.gateway.irc.connectport", 7000) };
String username = registration.getUsername();
String password = registration.getPassword();
password = (password == null || password.equals("")) ? null : password;
String nickname = registration.getNickname();
conn = new IRCConnection(server, ports, password, nickname, username, "Openfire User");
conn.setPong(true);
conn.setDaemon(false);
conn.setColors(false);
ircListener = new IRCListener(this);
conn.addIRCEventListener(ircListener);
}
/**
* Our pseudo roster.
*
* No server side buddy list, so we track it all here.
*/
private PseudoRoster pseudoRoster;
/**
* IRC connection.
*/
public IRCConnection conn;
/**
* IRC listener.
*/
IRCListener ircListener;
/**
* Tracks status of 'buddy list'.
*/
ConcurrentHashMap<String, PresenceType> buddyStatuses = new ConcurrentHashMap<String, PresenceType>();
/**
* Logs the session into IRC.
*
* @param presenceType Initial presence state.
* @param verboseStatus Initial full status information.
*/
public void logIn(PresenceType presenceType, String verboseStatus) {
try {
conn.connect();
setLoginStatus(TransportLoginStatus.LOGGED_IN);
}
catch (IOException e) {
Log.error("IO error while connecting to IRC: ", e);
}
}
/**
* Logs the session out of IRC.
*/
public void logOut() {
ircListener.setSilenced(true);
conn.doQuit();
cleanUp();
sessionDisconnectedNoReconnect();
}
public void cleanUp() {
ircListener.getTimer().cancel();
conn.close();
}
/**
* Retrieves the buddy status list.
*
* @return Hash of buddies mapped to presence type.
*/
public ConcurrentHashMap<String, PresenceType> getBuddyStatuses() {
return buddyStatuses;
}
/**
* Gets the current presence status of a buddy.
*
* @param username Username to look up.
* @return Presence type of a particular buddy.
*/
public PresenceType getBuddyStatus(String username) {
return buddyStatuses.get(username);
}
/**
* Updates the current presence status of a buddy.
*
* @param username Username to set presence of.
* @param presenceType New presence type.
*/
public void setBuddyStatus(String username, PresenceType presenceType) {
PresenceType buddyPresenceType = buddyStatuses.get(username);
if (buddyPresenceType == null || !buddyPresenceType.equals(presenceType)) {
Presence p = new Presence();
if (presenceType.equals(PresenceType.unavailable)) {
p.setType(Presence.Type.unavailable);
}
p.setTo(getJID());
p.setFrom(getTransport().convertIDToJID(username));
getTransport().sendPacket(p);
}
buddyStatuses.put(username, presenceType);
}
/**
* @return the IRC connection associated with this session.
*/
public IRCConnection getConnection() {
return conn;
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateStatus(org.jivesoftware.openfire.gateway.PresenceType, String)
*/
public void updateStatus(PresenceType presenceType, String verboseStatus) {
String awayMsg = ((IRCTransport)getTransport()).convertJabStatusToIRC(presenceType, verboseStatus);
if (awayMsg == null) {
conn.doAway();
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
}
else {
conn.doAway(awayMsg);
Presence p = new Presence();
p.setShow(Presence.Show.away);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#addContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void addContact(RosterItem item) {
String contact = getTransport().convertJIDToID(item.getJid());
if (pseudoRoster.hasItem(contact)) {
PseudoRosterItem rosterItem = pseudoRoster.getItem(contact);
rosterItem.setNickname(item.getNickname());
rosterItem.setGroups(item.getGroups().toString());
conn.doIson(contact);
}
else {
pseudoRoster.createItem(contact, item.getNickname(), item.getGroups().toString());
buddyStatuses.put(contact, PresenceType.unavailable);
conn.doIson(contact);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#removeContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void removeContact(RosterItem item) {
String contact = getTransport().convertJIDToID(item.getJid());
pseudoRoster.removeItem(contact);
buddyStatuses.remove(contact);
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void updateContact(RosterItem item) {
String contact = getTransport().convertJIDToID(item.getJid());
if (pseudoRoster.hasItem(contact)) {
PseudoRosterItem rosterItem = pseudoRoster.getItem(contact);
rosterItem.setNickname(item.getNickname());
rosterItem.setGroups(item.getGroups().toString());
conn.doIson(contact);
}
else {
pseudoRoster.createItem(contact, item.getNickname(), item.getGroups().toString());
buddyStatuses.put(contact, PresenceType.unavailable);
conn.doIson(contact);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendMessage(org.xmpp.packet.JID, String)
*/
public void sendMessage(JID jid, String message) {
conn.doPrivmsg(getTransport().convertJIDToID(jid), message);
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendServerMessage(String)
*/
public void sendServerMessage(String message) {
conn.send(message);
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendChatState(org.xmpp.packet.JID, org.jivesoftware.openfire.gateway.ChatStateType)
*/
public void sendChatState(JID jid, ChatStateType chatState) {
// IRC doesn't support this
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#retrieveContactStatus(org.xmpp.packet.JID)
*/
public void retrieveContactStatus(JID jid) {
if (isLoggedIn()) {
String contact = getTransport().convertJIDToID(jid);
Presence p = new Presence();
if (buddyStatuses.containsKey(contact)) {
if (buddyStatuses.get(contact).equals(PresenceType.unavailable)) {
p.setType(Presence.Type.unavailable);
}
}
else {
p.setError(PacketError.Condition.forbidden);
}
p.setTo(jid);
p.setFrom(getTransport().convertIDToJID(contact));
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#resendContactStatuses(org.xmpp.packet.JID)
*/
public void resendContactStatuses(JID jid) {
for (String contact : buddyStatuses.keySet()) {
Presence p = new Presence();
if (buddyStatuses.get(contact).equals(PresenceType.unavailable)) {
p.setType(Presence.Type.unavailable);
}
p.setTo(jid);
p.setFrom(getTransport().convertIDToJID(contact));
getTransport().sendPacket(p);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.irc;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.util.LocaleUtils;
import org.xmpp.packet.JID;
/***
* IRC Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class IRCTransport extends BaseTransport {
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyUsername()
*/
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway.irc.username", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyPassword()
*/
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway.irc.password", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyNickname()
*/
public String getTerminologyNickname() {
return LocaleUtils.getLocalizedString("gateway.irc.nickname", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyRegistration()
*/
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway.irc.registration", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isPasswordRequired()
*/
public Boolean isPasswordRequired() { return false; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isNicknameRequired()
*/
public Boolean isNicknameRequired() { return true; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isUsernameValid(String)
*/
public Boolean isUsernameValid(String username) {
return username.matches("\\w+");
}
/**
* Handles creating a IRC session and triggering a login.
*
* @param registration Registration information to be used to log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new IRCSession(registration, jid, this, priority);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
/**
* Handles logging out of a IRC session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
* Converts a jabber status to an IRC away message (or not).
*
* @param jabStatus Jabber presence type.
* @param verboseStatus Verbose status information.
* @return IRC status string.
*/
public String convertJabStatusToIRC(PresenceType jabStatus, String verboseStatus) {
if (jabStatus == PresenceType.available) {
return null;
}
else if (jabStatus == PresenceType.away) {
return verboseStatus.equals("") ? LocaleUtils.getLocalizedString("gateway.irc.away", "gateway") : LocaleUtils.getLocalizedString("gateway.irc.away", "gateway")+": "+verboseStatus;
}
else if (jabStatus == PresenceType.xa) {
return verboseStatus.equals("") ? LocaleUtils.getLocalizedString("gateway.irc.extendedaway", "gateway") : LocaleUtils.getLocalizedString("gateway.irc.extendedaway", "gateway")+": "+verboseStatus;
}
else if (jabStatus == PresenceType.dnd) {
return verboseStatus.equals("") ? LocaleUtils.getLocalizedString("gateway.irc.donotdisturb", "gateway") : LocaleUtils.getLocalizedString("gateway.irc.donotdisturb", "gateway")+": "+verboseStatus;
}
else if (jabStatus == PresenceType.chat) {
return null;
}
else if (jabStatus == PresenceType.unavailable) {
// This should never show up.
return null;
}
else {
return null;
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.msn;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import net.sf.jml.event.MsnAdapter;
import net.sf.jml.*;
import net.sf.jml.message.MsnInstantMessage;
import net.sf.jml.message.MsnControlMessage;
import net.sf.jml.message.MsnDatacastMessage;
import net.sf.jml.message.MsnUnknownMessage;
import java.util.Date;
import java.util.TimerTask;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
/**
* MSN Listener Interface.
*
* This handles real interaction with MSN, but mostly is a listener for
* incoming events from MSN.
*
* @author Daniel Henninger
*/
public class MSNListener extends MsnAdapter {
/**
* Creates the MSN Listener instance.
*
* @param session Session this listener is associated with.
*/
public MSNListener(MSNSession session) {
this.msnSession = session;
sessionReaper = new SessionReaper();
timer.schedule(sessionReaper, reaperInterval, reaperInterval);
}
/**
* The session this listener is associated with.
*/
public MSNSession msnSession = null;
/**
* Timer to check for stale typing notifications.
*/
private Timer timer = new Timer();
/**
* Interval at which typing notifications are reaped.
*/
private int reaperInterval = 5000; // 5 seconds
/**
* The actual repear task.
*/
private SessionReaper sessionReaper;
/**
* Record of active typing notifications.
*/
private ConcurrentHashMap<String,Date> typingNotificationMap = new ConcurrentHashMap<String,Date>();
/**
* Handles incoming messages from MSN users.
*/
public void instantMessageReceived(MsnSwitchboard switchboard, MsnInstantMessage message, MsnContact friend) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().convertIDToJID(friend.getEmail().toString()),
message.getContent()
);
}
/**
* Handles incoming system messages from MSN.
*
* @param switchboard Switchboard session the message is associated with.
* @param message MSN message.
*/
public void systemMessageReceived(MsnSwitchboard switchboard, MsnInstantMessage message) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
message.getContent()
);
}
/**
* Handles incoming control messages from MSN.
*/
public void controlMessageReceived(MsnSwitchboard switchboard, MsnControlMessage message, MsnContact friend) {
if (message.getTypingUser() != null) {
msnSession.getTransport().sendComposingNotification(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().convertIDToJID(friend.getEmail().toString())
);
typingNotificationMap.put(friend.getEmail().toString(), new Date());
}
else {
Log.debug("MSN: Received unknown control msg to " + switchboard + " from " + friend + ": " + message);
}
}
/**
* Handles incoming datacast messages from MSN.
*/
public void datacastMessageReceived(MsnSwitchboard switchboard, MsnDatacastMessage message, MsnContact friend) {
if (message.getId() == 1) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().convertIDToJID(friend.getEmail().toString()),
LocaleUtils.getLocalizedString("gateway.msn.nudge", "gateway"),
Message.Type.headline
);
}
else if (message.getId() == 2) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().convertIDToJID(friend.getEmail().toString()),
LocaleUtils.getLocalizedString("gateway.msn.wink", "gateway"),
Message.Type.headline
);
}
else {
Log.debug("MSN: Received unknown datacast message to " + switchboard + " from " + friend + ": " + message);
}
}
/**
* Handles incoming unknown messages from MSN.
*/
public void unknownMessageReceived(MsnSwitchboard switchboard, MsnUnknownMessage message, MsnContact friend) {
Log.debug("MSN: Received unknown message to " + switchboard + " from " + friend + ": " + message);
}
/**
* The user's login has completed and was accepted.
*/
public void loginCompleted(MsnMessenger messenger) {
Log.debug("MSN: Login completed for "+messenger.getOwner().getEmail());
msnSession.getRegistration().setLastLogin(new Date());
msnSession.setLoginStatus(TransportLoginStatus.LOGGED_IN);
}
/**
* Contact list has been synced.
*/
public void contactListSyncCompleted(MsnMessenger messenger) {
Log.debug("MSN: Contact list sync for "+messenger.getOwner().getEmail());
}
/**
* Contact list initialization has completed.
*/
public void contactListInitCompleted(MsnMessenger messenger) {
for (MsnContact msnContact : messenger.getContactList().getContacts()) {
Log.debug("MSN: Got contact "+msnContact);
if (msnContact.isInList(MsnList.FL) && msnContact.getEmail() != null) {
msnSession.storeFriend(msnContact);
}
}
for (MsnGroup msnGroup : messenger.getContactList().getGroups()) {
Log.debug("MSN: Got group "+msnGroup);
msnSession.storeGroup(msnGroup);
}
msnSession.syncUsers();
}
/**
* A friend for this user has changed status.
*/
public void contactStatusChanged(MsnMessenger messenger, MsnContact friend) {
if (!friend.isInList(MsnList.FL) || friend.getEmail() == null) {
// Not in our buddy list, don't care, or null email address. We need that.
return;
}
Presence p = new Presence();
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().convertIDToJID(friend.getEmail().toString()));
((MSNTransport)msnSession.getTransport()).setUpPresencePacket(p, friend.getStatus());
msnSession.getTransport().sendPacket(p);
msnSession.storeFriend(friend);
}
/**
* Someone added us to their contact list.
*/
public void contactAddedMe(MsnMessenger messenger, MsnContact friend) {
Presence p = new Presence();
p.setType(Presence.Type.subscribe);
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().convertIDToJID(friend.getEmail().toString()));
msnSession.getTransport().sendPacket(p);
}
/**
* Someone removed us from their contact list.
*/
public void contactRemovedMe(MsnMessenger messenger, MsnContact friend) {
Presence p = new Presence();
p.setType(Presence.Type.unsubscribe);
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().convertIDToJID(friend.getEmail().toString()));
msnSession.getTransport().sendPacket(p);
}
/**
* A contact we added has been added to the server.
*/
public void contactAddCompleted(MsnMessenger messenger, MsnContact contact) {
Log.debug("MSN: Contact add completed: "+contact);
Presence p = new Presence();
p.setType(Presence.Type.subscribed);
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().convertIDToJID(contact.getEmail().toString()));
msnSession.getTransport().sendPacket(p);
msnSession.storeFriend(contact);
msnSession.completedPendingContactAdd(contact);
}
/**
* A contact we removed has been removed from the server.
*/
public void contactRemoveCompleted(MsnMessenger messenger, MsnContact contact) {
Log.debug("MSN: Contact remove completed: "+contact);
Presence p = new Presence();
p.setType(Presence.Type.unsubscribed);
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().convertIDToJID(contact.getEmail().toString()));
msnSession.getTransport().sendPacket(p);
msnSession.unstoreFriend(contact);
}
/**
* A group we added has been added to the server.
*/
public void groupAddCompleted(MsnMessenger messenger, MsnGroup group) {
Log.debug("MSN: Group add completed: "+group);
msnSession.storeGroup(group);
msnSession.completedPendingGroupAdd(group);
}
/**
* A group we removed has been removed from the server.
*/
public void groupRemoveCompleted(MsnMessenger messenger, MsnGroup group) {
Log.debug("MSN: Group remove completed: "+group);
msnSession.unstoreGroup(group);
}
/**
* Owner status has changed.
*/
public void ownerStatusChanged(MsnMessenger messenger) {
Presence p = new Presence();
p.setTo(msnSession.getJID());
p.setFrom(msnSession.getTransport().getJID());
((MSNTransport)msnSession.getTransport()).setUpPresencePacket(p, messenger.getOwner().getStatus());
msnSession.getTransport().sendPacket(p);
}
/**
* Catches MSN exceptions.
*/
public void exceptionCaught(MsnMessenger messenger, Throwable throwable) {
Log.debug("MSN: Exception occurred for "+messenger.getOwner().getEmail()+" : "+throwable);
if (throwable.getClass().getName().equals("net.sf.jml.exception.IncorrectPasswordException")) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.msn.passwordincorrect", "gateway"),
Message.Type.error
);
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
else if (throwable.getClass().getName().equals("net.sf.jml.exception.MsnProtocolException")) {
Log.debug("MSN: Protocol exception: "+throwable.toString());
}
else if (throwable.getClass().getName().equals("net.sf.jml.exception.MsgNotSendException")) {
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.msn.sendmsgfailed", "gateway")+" "+throwable.toString(),
Message.Type.error
);
}
else if (throwable.getClass().getName().equals("net.sf.jml.exception.UnknownMessageException")) {
Log.debug("MSN: Unknown message: "+throwable.toString());
}
else if (throwable.getClass().getName().equals("net.sf.jml.exception.UnsupportedProtocolException")) {
Log.debug("MSN: Protocol error: "+throwable.toString());
}
else if (throwable.getClass().getName().equals("java.io.IOException")) {
Log.debug("MSN: IO error: "+throwable.toString());
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.msn.disconnect", "gateway"),
Message.Type.error
);
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnected();
}
else {
Log.debug("MSN: Unknown error: "+throwable.toString());
}
}
/**
* Clean up any active typing notifications that are stale.
*/
private class SessionReaper extends TimerTask {
/**
* Silence any typing notifications that are stale.
*/
public void run() {
cancelTypingNotifications();
}
}
/**
* Any typing notification that hasn't been heard in 10 seconds will be killed.
*/
private void cancelTypingNotifications() {
for (String source : typingNotificationMap.keySet()) {
if (typingNotificationMap.get(source).getTime() < ((new Date().getTime()) - 10000)) {
msnSession.getTransport().sendChatInactiveNotification(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().convertIDToJID(source)
);
typingNotificationMap.remove(source);
}
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.msn;
import net.sf.jml.*;
import net.sf.jml.message.MsnControlMessage;
import net.sf.jml.impl.BasicMessenger;
import net.sf.jml.impl.MsnMessengerFactory;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Message;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a MSN session.
*
* This is the interface with which the base transport functionality will
* communicate with MSN.
*
* @author Daniel Henninger
*/
public class MSNSession extends TransportSession {
/**
* Create a MSN Session instance.
*
* @param registration Registration informationed used for logging in.
* @param jid JID associated with this session.
* @param transport Transport instance associated with this session.
* @param priority Priority of this session.
*/
public MSNSession(Registration registration, JID jid, MSNTransport transport, Integer priority) {
super(registration, jid, transport, priority);
if (Email.parseStr(registration.getUsername()) == null) {
Message m = new Message();
m.setType(Message.Type.error);
m.setTo(getJID());
m.setFrom(getTransport().getJID());
m.setBody(LocaleUtils.getLocalizedString("gateway.msn.illegalaccount", "gateway")+" "+registration.getUsername());
return;
}
Log.debug("Creating MSN session for " + registration.getUsername());
msnMessenger = MsnMessengerFactory.createMsnMessenger(registration.getUsername(), registration.getPassword());
((BasicMessenger)msnMessenger).addSessionListener(new MSNSessionListener(this));
msnMessenger.setSupportedProtocol(new MsnProtocol[] { MsnProtocol.MSNP11 });
}
/**
* MSN session
*/
private MsnMessenger msnMessenger = null;
/**
* MSN contacts/friends.
*/
private ConcurrentHashMap<String,MsnContact> msnContacts = new ConcurrentHashMap<String,MsnContact>();
/**
* MSN groups.
*/
private ConcurrentHashMap<String,MsnGroup> msnGroups = new ConcurrentHashMap<String,MsnGroup>();
/**
* Pending MSN groups and contact to be added.
*/
private ConcurrentHashMap<String,ArrayList<Email>> msnPendingGroups = new ConcurrentHashMap<String,ArrayList<Email>>();
/**
* Log in to MSN.
*
* @param presenceType Type of presence.
* @param verboseStatus Long representation of status.
*/
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!isLoggedIn()) {
try {
Log.debug("Logging in to MSN session for " + msnMessenger.getOwner().getEmail());
msnMessenger.getOwner().setInitStatus(((MSNTransport)getTransport()).convertJabStatusToMSN(presenceType));
msnMessenger.setLogIncoming(false);
msnMessenger.setLogOutgoing(false);
msnMessenger.addListener(new MSNListener(this));
((BasicMessenger)msnMessenger).login(
JiveGlobals.getProperty("plugin.gateway.msn.connecthost", "messenger.hotmail.com"),
JiveGlobals.getIntProperty("plugin.gateway.msn.connectport", 1863));
}
catch (Exception e) {
Log.error("MSN user is not able to log in: " + msnMessenger.getOwner().getEmail(), e);
}
}
}
/**
* Log out of MSN.
*/
public void logOut() {
cleanUp();
sessionDisconnectedNoReconnect();
}
public void cleanUp() {
msnMessenger.logout();
}
/**
* Retrieves the manager for this session.
*
* @return Messenger instance the session is associated with.
*/
public MsnMessenger getManager() {
return msnMessenger;
}
/**
* Records information about a person on the user's contact list.
*
* @param msnContact MSN contact we are storing a copy of.
*/
public void storeFriend(MsnContact msnContact) {
msnContacts.put(msnContact.getEmail().toString(), msnContact);
}
/**
* Removes information about a person from the user's contact list.
*
* @param msnContact MSN contact we are removing a copy of.
*/
public void unstoreFriend(MsnContact msnContact) {
msnContacts.remove(msnContact.getEmail().toString());
}
/**
* Records information about a group on the user's contact list.
*
* @param msnGroup MSN group we are storing a copy of.
*/
public void storeGroup(MsnGroup msnGroup) {
msnGroups.put(msnGroup.getGroupName(), msnGroup);
}
/**
* Removes information about a group from the user's contact list.
*
* @param msnGroup MSN group we are removing a copy of.
*/
public void unstoreGroup(MsnGroup msnGroup) {
msnGroups.remove(msnGroup.getGroupName());
}
/**
* Records a member of a pending new group that will be added later.
*
* @param groupName Name of group to be stored.
* @param member Email address of member to be added.
*/
public void storePendingGroup(String groupName, Email member) {
if (!msnPendingGroups.containsKey(groupName)) {
ArrayList<Email> newList = new ArrayList<Email>();
newList.add(member);
msnPendingGroups.put(groupName, newList);
}
else {
ArrayList<Email> list = msnPendingGroups.get(groupName);
list.add(member);
msnPendingGroups.put(groupName, list);
}
}
/**
* Completes the addition of groups to a new contact after the contact has been created.
*
* @param msnContact Contact that was added.
*/
public void completedPendingContactAdd(MsnContact msnContact) {
try {
Roster roster = getTransport().getRosterManager().getRoster(getJID().getNode());
Email contact = msnContact.getEmail();
JID contactJID = getTransport().convertIDToJID(contact.toString());
RosterItem item = roster.getRosterItem(contactJID);
syncContactGroups(contact, item.getGroups());
unlockRoster(contactJID.toString());
}
catch (UserNotFoundException e) {
Log.error("MSN: Unable to find roster when adding pendingcontact for "+getJID());
Email contact = msnContact.getEmail();
JID contactJID = getTransport().convertIDToJID(contact.toString());
unlockRoster(contactJID.toString());
}
}
/**
* Completes the addition of a contact to a new group after the group has been created.
*
* @param msnGroup Group that was added.
*/
public void completedPendingGroupAdd(MsnGroup msnGroup) {
if (!msnPendingGroups.containsKey(msnGroup.getGroupName())) {
// Nothing to do, no pending.
return;
}
try {
Roster roster = getTransport().getRosterManager().getRoster(getJID().getNode());
for (Email contact : msnPendingGroups.get(msnGroup.getGroupName())) {
JID contactJID = getTransport().convertIDToJID(contact.toString());
RosterItem item = roster.getRosterItem(contactJID);
lockRoster(contactJID.toString());
syncContactGroups(contact, item.getGroups());
unlockRoster(contactJID.toString());
}
}
catch (UserNotFoundException e) {
Log.error("MSN: Unable to find roster when adding pending group contacts for "+getJID());
}
}
/**
* Syncs up the MSN roster with the jabber roster.
*/
public void syncUsers() {
List<TransportBuddy> legacyusers = new ArrayList<TransportBuddy>();
for (MsnContact friend : msnContacts.values()) {
ArrayList<String> friendGroups = new ArrayList<String>();
for (MsnGroup group : friend.getBelongGroups()) {
Log.debug("MSN: Found belong group for "+friend+" as "+group);
friendGroups.add(group.getGroupName());
}
if (friendGroups.size() > 0) {
legacyusers.add(new TransportBuddy(friend.getEmail().toString(), friend.getFriendlyName(), friendGroups.get(0)));
}
else {
legacyusers.add(new TransportBuddy(friend.getEmail().toString(), friend.getFriendlyName(), null));
}
}
try {
getTransport().syncLegacyRoster(getJID(), legacyusers);
}
catch (UserNotFoundException e) {
Log.error("Unable to sync MSN contact list for " + getJID(), e);
}
// Lets send initial presence statuses
for (MsnContact friend : msnContacts.values()) {
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().convertIDToJID(friend.getEmail().toString()));
((MSNTransport)getTransport()).setUpPresencePacket(p, friend.getStatus());
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#addContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void addContact(RosterItem item) {
Email contact = Email.parseStr(getTransport().convertJIDToID(item.getJid()));
if (contact == null) {
Log.error("MSN: Unable to update illegal contact "+item.getJid());
return;
}
String nickname = getTransport().convertJIDToID(item.getJid());
if (item.getNickname() != null && !item.getNickname().equals("")) {
nickname = item.getNickname();
}
lockRoster(item.getJid().toString());
msnMessenger.addFriend(contact, nickname);
try {
getTransport().addOrUpdateRosterItem(getJID(), item.getJid(), nickname, item.getGroups());
}
catch (UserNotFoundException e) {
Log.error("MSN: Unable to find roster when adding contact.");
}
// syncContactGroups(contact, item.getGroups());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#removeContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void removeContact(RosterItem item) {
Email contact = Email.parseStr(getTransport().convertJIDToID(item.getJid()));
if (contact == null) {
Log.error("MSN: Unable to update illegal contact "+item.getJid());
return;
}
lockRoster(item.getJid().toString());
msnMessenger.removeFriend(contact, false);
unlockRoster(item.getJid().toString());
msnContacts.remove(contact.toString());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void updateContact(RosterItem item) {
Email contact = Email.parseStr(getTransport().convertJIDToID(item.getJid()));
if (contact == null) {
Log.error("MSN: Unable to update illegal contact "+item.getJid());
return;
}
String nickname = getTransport().convertJIDToID(item.getJid());
if (item.getNickname() != null && !item.getNickname().equals("")) {
nickname = item.getNickname();
}
MsnContact msnContact = msnContacts.get(contact.toString());
if (msnContact == null) {
return;
}
lockRoster(item.getJid().toString());
if (!msnContact.getFriendlyName().equals(nickname)) {
msnMessenger.renameFriend(contact, nickname);
}
syncContactGroups(contact, item.getGroups());
unlockRoster(item.getJid().toString());
}
/**
* Given a legacy contact and a list of groups, makes sure that the list is in sync with
* the actual group list.
*
* @param contact Email address of contact.
* @param groups List of groups contact should be in.
*/
public void syncContactGroups(Email contact, List<String> groups) {
MsnContact msnContact = msnContacts.get(contact.toString());
if (msnContact == null) {
return;
}
// Create groups that do not currently exist.
for (String group : groups) {
if (!msnGroups.containsKey(group)) {
Log.debug("MSN: Group "+group+" is a new group, creating.");
msnMessenger.addGroup(group);
// Ok, short circuit here, we need to wait for this group to be added. We'll be back.
storePendingGroup(group, contact);
return;
}
}
// Make sure contact belongs to groups that we want.
for (String group : groups) {
Log.debug("MSN: Found "+contact+" should belong to group "+group);
MsnGroup msnGroup = msnGroups.get(group);
if (msnGroup != null && !msnContact.belongGroup(msnGroup)) {
Log.debug("MSN: "+contact+" does not belong to "+group+", copying.");
msnMessenger.copyFriend(contact, msnGroup.getGroupId());
}
}
// Now we will clean up groups that we should no longer belong to.
for (MsnGroup msnGroup : msnContact.getBelongGroups()) {
Log.debug("MSN: Found "+contact+" belongs to group "+msnGroup.getGroupName());
if (!groups.contains(msnGroup.getGroupName())) {
Log.debug("MSN: "+contact+" should not belong to "+msnGroup.getGroupName()+", removing.");
msnMessenger.removeFriend(contact, msnGroup.getGroupId());
}
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendMessage(org.xmpp.packet.JID, String)
*/
public void sendMessage(JID jid, String message) {
msnMessenger.sendText(Email.parseStr(getTransport().convertJIDToID(jid)), message);
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendServerMessage(String)
*/
public void sendServerMessage(String message) {
// We don't care.
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendChatState(org.xmpp.packet.JID, org.jivesoftware.openfire.gateway.ChatStateType)
*/
public void sendChatState(JID jid, ChatStateType chatState) {
if (chatState.equals(ChatStateType.composing)) {
Email jidEmail = Email.parseStr(getTransport().convertJIDToID(jid));
MsnControlMessage mcm = new MsnControlMessage();
mcm.setTypingUser(msnMessenger.getOwner().getEmail().getEmailAddress());
for (MsnSwitchboard sb : msnMessenger.getActiveSwitchboards()) {
if (sb.containContact(jidEmail)) {
sb.sendMessage(mcm, true);
}
}
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#retrieveContactStatus(org.xmpp.packet.JID)
*/
public void retrieveContactStatus(JID jid) {
if (isLoggedIn()) {
MsnContact msnContact = msnContacts.get(getTransport().convertJIDToID(jid));
Presence p = new Presence();
p.setTo(getJID());
if (msnContact != null) {
p.setFrom(getTransport().convertIDToJID(msnContact.getEmail().toString()));
((MSNTransport)getTransport()).setUpPresencePacket(p, msnContact.getStatus());
}
else {
// User was not found so send an error presence
p.setFrom(jid);
p.setError(PacketError.Condition.forbidden);
}
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateStatus(org.jivesoftware.openfire.gateway.PresenceType, String)
*/
public void updateStatus(PresenceType presenceType, String verboseStatus) {
if (isLoggedIn()) {
try {
msnMessenger.getOwner().setStatus(((MSNTransport)getTransport()).convertJabStatusToMSN(presenceType));
}
catch (IllegalStateException e) {
// // Hrm, not logged in? Lets fix that.
// msnMessenger.getOwner().setInitStatus(((MSNTransport)getTransport()).convertJabStatusToMSN(presenceType));
// msnMessenger.login();
}
}
else {
// // Hrm, not logged in? Lets fix that.
// msnMessenger.getOwner().setInitStatus(((MSNTransport)getTransport()).convertJabStatusToMSN(presenceType));
// msnMessenger.login();
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#resendContactStatuses(org.xmpp.packet.JID)
*/
public void resendContactStatuses(JID jid) {
for (MsnContact friend : msnContacts.values()) {
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().convertIDToJID(friend.getEmail().toString()));
((MSNTransport)getTransport()).setUpPresencePacket(p, friend.getStatus());
getTransport().sendPacket(p);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.msn;
import net.sf.cindy.SessionAdapter;
import net.sf.cindy.Session;
import net.sf.cindy.Message;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
/**
* MSN Session Listener Interface.
*
* This handles listening to session activities.
*
* @author lionheart@clansk.org
* @author Daniel Henninger
*/
public class MSNSessionListener extends SessionAdapter {
public MSNSessionListener(MSNSession msnSession) {
this.msnSession = msnSession;
}
/**
* The session this listener is associated with.
*/
public MSNSession msnSession = null;
public void exceptionCaught(Session arg0, Throwable t) throws Exception{
Log.debug("MSN: Session exceptionCaught for "+msnSession.getRegistration().getUsername()+" : "+t);
}
public void messageReceived(Session arg0, Message message) throws Exception {
Log.debug("MSN: Session messageReceived for "+msnSession.getRegistration().getUsername()+" : "+message);
// TODO: Kinda hacky, would like to improve on this later.
if (message.toString().startsWith("OUT OTH")) {
// Forced disconnect because account logged in elsewhere
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.msn.otherloggedin", "gateway"),
org.xmpp.packet.Message.Type.error
);
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
else if (message.toString().startsWith("OUT SDH")) {
// Forced disconnect from server for maintenance
msnSession.getTransport().sendMessage(
msnSession.getJIDWithHighestPriority(),
msnSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.msn.disconnect", "gateway"),
org.xmpp.packet.Message.Type.error
);
msnSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
msnSession.sessionDisconnectedNoReconnect();
}
}
public void messageSent(Session arg0, Message message) throws Exception {
Log.debug("MSN: Session messageSent for "+msnSession.getRegistration().getUsername()+" : "+message);
}
public void sessionIdle(Session session) throws Exception {
}
public void sessionEstablished(Session session) {
Log.debug("MSN: Session established for "+msnSession.getRegistration().getUsername());
}
public void sessionTimeout(Session session) {
// This is used to handle regular pings to the MSN server. No need to mention it.
}
public void sessionClosed(Session session) {
Log.debug("MSN: Session closed for "+msnSession.getRegistration().getUsername());
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.msn;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import net.sf.jml.MsnUserStatus;
/**
* MSN Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class MSNTransport extends BaseTransport {
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyUsername()
*/
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway.msn.username", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyPassword()
*/
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway.msn.password", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyNickname()
*/
public String getTerminologyNickname() {
return null;
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyRegistration()
*/
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway.msn.registration", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isPasswordRequired()
*/
public Boolean isPasswordRequired() { return true; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isNicknameRequired()
*/
public Boolean isNicknameRequired() { return false; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isUsernameValid(String)
*/
public Boolean isUsernameValid(String username) {
return username.matches("[^ \\p{Cntrl}()@,;:\\\\\"\\[\\]]+@[^ \\p{Cntrl}()@,;:\\\\\"\\[\\]]+");
}
/**
* Handles creating a MSN session and triggering a login.
*
* @param registration Registration information to be used to log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new MSNSession(registration, jid, this, priority);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
/**
* Handles logging out of a MSN session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
* Converts a jabber status to an MSN status.
*
* @param jabStatus Jabber presence type.
* @return MSN user status id.
*/
public MsnUserStatus convertJabStatusToMSN(PresenceType jabStatus) {
if (jabStatus == PresenceType.available) {
return MsnUserStatus.ONLINE;
}
else if (jabStatus == PresenceType.away) {
return MsnUserStatus.AWAY;
}
else if (jabStatus == PresenceType.xa) {
return MsnUserStatus.AWAY;
}
else if (jabStatus == PresenceType.dnd) {
return MsnUserStatus.BUSY;
}
else if (jabStatus == PresenceType.chat) {
return MsnUserStatus.ONLINE;
}
else if (jabStatus == PresenceType.unavailable) {
return MsnUserStatus.OFFLINE;
}
else {
return MsnUserStatus.ONLINE;
}
}
/**
* Sets up a presence packet according to MSN status.
*
* @param msnStatus MSN ContactStatus constant.
* @param packet Presence packet to set up.
*/
public void setUpPresencePacket(Presence packet, MsnUserStatus msnStatus) {
if (msnStatus.equals(MsnUserStatus.ONLINE)) {
// We're good, send as is..
}
else if (msnStatus.equals(MsnUserStatus.AWAY)) {
packet.setShow(Presence.Show.away);
}
else if (msnStatus.equals(MsnUserStatus.BE_RIGHT_BACK)) {
packet.setShow(Presence.Show.away);
}
else if (msnStatus.equals(MsnUserStatus.BUSY)) {
packet.setShow(Presence.Show.dnd);
}
else if (msnStatus.equals(MsnUserStatus.IDLE)) {
packet.setShow(Presence.Show.away);
}
else if (msnStatus.equals(MsnUserStatus.OFFLINE)) {
packet.setType(Presence.Type.unavailable);
}
else if (msnStatus.equals(MsnUserStatus.ON_THE_PHONE)) {
packet.setShow(Presence.Show.dnd);
}
else if (msnStatus.equals(MsnUserStatus.OUT_TO_LUNCH)) {
packet.setShow(Presence.Show.xa);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.*;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.*;
import net.kano.joscar.snaccmd.icq.OfflineMsgIcqCmd;
import net.kano.joscar.snaccmd.icq.OfflineMsgDoneCmd;
import net.kano.joscar.snaccmd.icq.OfflineMsgIcqAckCmd;
import net.kano.joscar.snaccmd.icq.MetaShortInfoCmd;
import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.icbm.*;
import net.kano.joscar.snaccmd.loc.*;
import net.kano.joscar.snaccmd.ssi.*;
import net.kano.joscar.ssiitem.*;
import java.util.Arrays;
import java.util.List;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.xmpp.packet.Presence;
/**
* Handles BOS related packets.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public class BOSConnection extends BasicFlapConnection {
protected SsiItemObjectFactory itemFactory = new DefaultSsiItemObjFactory();
private static final List<CapabilityBlock> MY_CAPS = Arrays.asList(
CapabilityBlock.BLOCK_ICQCOMPATIBLE
);
public BOSConnection(ConnDescriptor cd, OSCARSession mainSession, ByteBlock cookie) {
super(cd, mainSession, cookie); // Hand off to BasicFlapConnection
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("OSCAR bos service state change from "+e.getOldState()+" to "+e.getNewState());
if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED && e.getOldState() == ClientFlapConn.STATE_CONNECTED && getMainSession().isLoggedIn()) {
getMainSession().bosDisconnected();
}
}
protected void handleFlapPacket(FlapPacketEvent e) {
Log.debug("OSCAR bos flap packet received: "+e);
super.handleFlapPacket(e);
}
protected void handleSnacPacket(SnacPacketEvent e) {
Log.debug("OSCAR bos snac packet received: "+e);
super.handleSnacPacket(e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof ServerReadyCmd) {
request(new ParamInfoRequest());
request(new LocRightsRequest());
request(new SsiRightsRequest());
request(new SsiDataRequest());
}
}
protected void handleSnacResponse(SnacResponseEvent e) {
super.handleSnacResponse(e);
Log.debug("OSCAR bos snac response received: "+e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof LocRightsCmd) {
request(new SetInfoCmd(new InfoData("oscargateway",
null, MY_CAPS, null)));
request(new MyInfoRequest());
}
else if (cmd instanceof ParamInfoCmd) {
ParamInfoCmd pic = (ParamInfoCmd) cmd;
ParamInfo info = pic.getParamInfo();
request(new SetParamInfoCmd(new ParamInfo(0,
info.getFlags() | ParamInfo.FLAG_TYPING_NOTIFICATION, 8000,
info.getMaxSenderWarning(), info.getMaxReceiverWarning(),
0)));
}
else if (cmd instanceof ServiceRedirect) {
ServiceRedirect sr = (ServiceRedirect) cmd;
oscarSession.connectToService(sr.getSnacFamily(), sr.getRedirectHost(),
sr.getCookie());
}
else if (cmd instanceof SsiDataCmd) {
SsiDataCmd sdc = (SsiDataCmd) cmd;
List<SsiItem> items = sdc.getItems();
for (SsiItem item : items) {
SsiItemObj obj = itemFactory.getItemObj(item);
if (obj instanceof BuddyItem) {
Log.debug("AIM got buddy item " + obj);
oscarSession.gotBuddy((BuddyItem) obj);
}
else if (obj instanceof GroupItem) {
Log.debug("AIM got group item " + obj);
oscarSession.gotGroup((GroupItem) obj);
}
}
if (sdc.getLastModDate() != 0) {
request(new ActivateSsiCmd());
clientReady();
Presence p = new Presence();
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().getJID());
oscarSession.getTransport().sendPacket(p);
oscarSession.setLoginStatus(TransportLoginStatus.LOGGED_IN);
oscarSession.gotCompleteSSI();
}
}
else if (cmd instanceof OfflineMsgIcqCmd) {
OfflineMsgIcqCmd omic = (OfflineMsgIcqCmd)cmd;
String sn = String.valueOf(omic.getFromUIN());
//String msg = "Offline message sent at "+new Date(omic.getDate().getTime()).toString()+"\n"+OscarTools.stripHtml(omic.getContents()).trim();
String msg = "Offline message received:\n"+ StringUtils.unescapeFromXML(OscarTools.stripHtml(omic.getContents()).trim());
EncodedStringInfo encmsg = MinimalEncoder.encodeMinimally(msg);
InstantMessage imsg = new InstantMessage(encmsg.getImEncoding().getCharsetCode(), ByteBlock.wrap(encmsg.getData()));
oscarSession.getTransport().sendMessage(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(sn),
imsg.getMessage()
);
}
else if (cmd instanceof OfflineMsgDoneCmd) {
request(new OfflineMsgIcqAckCmd(oscarSession.getUIN(), (int)oscarSession.nextIcqId()));
}
else if (cmd instanceof MetaShortInfoCmd) {
// MetaShortInfoCmd msic = (MetaShortInfoCmd)cmd;
// Log.debug("RECEIVED META SHORT INFO: "+msic);
// oscarSession.updateRosterNickname(String.valueOf(msic.getUIN()), msic.getNickname());
}
else if (cmd instanceof BuddyAddedYouCmd) {
BuddyAddedYouCmd bay = (BuddyAddedYouCmd)cmd;
Presence p = new Presence();
p.setType(Presence.Type.subscribe);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(bay.getUin()));
oscarSession.getTransport().sendPacket(p);
}
else if (cmd instanceof BuddyAuthRequest) {
BuddyAuthRequest bar = (BuddyAuthRequest)cmd;
Presence p = new Presence();
p.setType(Presence.Type.subscribe);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(bar.getScreenname()));
oscarSession.getTransport().sendPacket(p);
}
else if (cmd instanceof AuthReplyCmd) {
AuthReplyCmd ar = (AuthReplyCmd)cmd;
if (ar.isAccepted()) {
Presence p = new Presence();
p.setType(Presence.Type.subscribed);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(ar.getSender()));
oscarSession.getTransport().sendPacket(p);
}
else {
Presence p = new Presence();
p.setType(Presence.Type.unsubscribed);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(ar.getSender()));
oscarSession.getTransport().sendPacket(p);
}
}
else if (cmd instanceof AuthFutureCmd) {
AuthFutureCmd af = (AuthFutureCmd)cmd;
Presence p = new Presence();
p.setType(Presence.Type.subscribe);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(af.getUin()));
oscarSession.getTransport().sendPacket(p);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import net.kano.joscar.flap.ClientFlapConn;
import net.kano.joscar.flap.FlapPacketListener;
import net.kano.joscar.flap.FlapPacketEvent;
import net.kano.joscar.snac.*;
import net.kano.joscar.flapcmd.DefaultFlapCmdFactory;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.snaccmd.DefaultClientFactoryList;
import net.kano.joscar.net.*;
/**
* Base class for all FLAP handlers.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public abstract class BaseFlapConnection extends ClientFlapConn {
protected ClientSnacProcessor sp = new ClientSnacProcessor(getFlapProcessor());
OSCARSession oscarSession;
public BaseFlapConnection(ConnDescriptor cd, OSCARSession mainSession) {
super(cd); // Hand off to ClientFlapConn
initBaseFlapConnection();
oscarSession = mainSession;
}
private void initBaseFlapConnection() {
getFlapProcessor().setFlapCmdFactory(new DefaultFlapCmdFactory());
sp.addPreprocessor(new FamilyVersionPreprocessor());
sp.getCmdFactoryMgr().setDefaultFactoryList(new DefaultClientFactoryList());
addConnListener(new ClientConnListener() {
public void stateChanged(ClientConnEvent e) {
handleStateChange(e);
}
});
getFlapProcessor().addPacketListener(new FlapPacketListener() {
public void handleFlapPacket(FlapPacketEvent e) {
BaseFlapConnection.this.handleFlapPacket(e);
}
});
getFlapProcessor().addExceptionHandler(new ConnProcessorExceptionHandler() {
public void handleException(ConnProcessorExceptionEvent event) {
Log.error(event.getType() + " FLAP ERROR: "
+ event.getException().getMessage() + " " + event.getReason());
}
});
sp.addPacketListener(new SnacPacketListener() {
public void handleSnacPacket(SnacPacketEvent e) {
BaseFlapConnection.this.handleSnacPacket(e);
}
});
}
protected SnacRequestListener genericReqListener = new SnacRequestAdapter() {
public void handleResponse(SnacResponseEvent e) {
handleSnacResponse(e);
}
};
public SnacRequestListener getGenericReqListener() {
return genericReqListener;
}
public ClientSnacProcessor getSnacProcessor() {
return sp;
}
public OSCARSession getMainSession() { return oscarSession; }
void sendRequest(SnacRequest req) {
if (!req.hasListeners()) req.addListener(genericReqListener);
sp.sendSnac(req);
}
SnacRequest request(SnacCommand cmd) {
return request(cmd, null);
}
SnacRequest request(SnacCommand cmd, SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
sendRequest(req);
return req;
}
protected abstract void handleStateChange(ClientConnEvent e);
protected abstract void handleFlapPacket(FlapPacketEvent e);
protected abstract void handleSnacPacket(SnacPacketEvent e);
protected abstract void handleSnacResponse(SnacResponseEvent e);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.StringUtils;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import net.kano.joscar.ByteBlock;
import net.kano.joscar.OscarTools;
import net.kano.joscar.BinaryTools;
import net.kano.joscar.net.ConnDescriptor;
import net.kano.joscar.flap.FlapCommand;
import net.kano.joscar.flap.FlapPacketEvent;
import net.kano.joscar.snac.SnacPacketEvent;
import net.kano.joscar.snac.SnacResponseEvent;
import net.kano.joscar.snac.SnacRequest;
import net.kano.joscar.snac.SnacRequestListener;
import net.kano.joscar.flapcmd.LoginFlapCmd;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.snaccmd.conn.*;
import net.kano.joscar.snaccmd.*;
import net.kano.joscar.snaccmd.icbm.RecvImIcbm;
import net.kano.joscar.snaccmd.icbm.InstantMessage;
import net.kano.joscar.snaccmd.icbm.TypingCmd;
import net.kano.joscar.snaccmd.icbm.OldIcbm;
import net.kano.joscar.snaccmd.buddy.BuddyStatusCmd;
import net.kano.joscar.snaccmd.buddy.BuddyOfflineCmd;
import net.kano.joscar.ratelim.RateLimitingQueueMgr;
/**
* Handles incoming FLAP packets.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public abstract class BasicFlapConnection extends BaseFlapConnection {
protected final ByteBlock cookie;
protected boolean sentClientReady = false;
public ConcurrentHashMap<String,FullUserInfo> buddystore = new ConcurrentHashMap<String, FullUserInfo>();
protected int[] snacFamilies = null;
protected Collection<SnacFamilyInfo> snacFamilyInfos;
protected RateLimitingQueueMgr rateMgr = new RateLimitingQueueMgr();
public BasicFlapConnection(ConnDescriptor cd, OSCARSession mainSession, ByteBlock cookie) {
super(cd, mainSession);
this.cookie = cookie;
initBasicFlapConnection();
}
private void initBasicFlapConnection() {
sp.setSnacQueueManager(rateMgr);
}
protected DateFormat dateFormat
= DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.SHORT);
protected void handleFlapPacket(FlapPacketEvent e) {
Log.debug("OSCAR flap packet received: "+e);
FlapCommand cmd = e.getFlapCommand();
if (cmd instanceof LoginFlapCmd) {
getFlapProcessor().sendFlap(new LoginFlapCmd(cookie));
}
}
protected void handleSnacPacket(SnacPacketEvent e) {
Log.debug("OSCAR snac packet received: "+e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof ServerReadyCmd) {
ServerReadyCmd src = (ServerReadyCmd) cmd;
setSnacFamilies(src.getSnacFamilies());
Collection<SnacFamilyInfo> familyInfos = SnacFamilyInfoFactory.getDefaultFamilyInfos(src.getSnacFamilies());
setSnacFamilyInfos(familyInfos);
oscarSession.registerSnacFamilies(this);
request(new ClientVersionsCmd(familyInfos));
request(new RateInfoRequest());
}
else if (cmd instanceof RecvImIcbm) {
RecvImIcbm icbm = (RecvImIcbm) cmd;
String sn = icbm.getSenderInfo().getScreenname();
InstantMessage message = icbm.getMessage();
String msg = StringUtils.unescapeFromXML(OscarTools.stripHtml(message.getMessage()));
oscarSession.getTransport().sendMessage(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(sn),
msg
);
}
else if (cmd instanceof OldIcbm) {
OldIcbm oicbm = (OldIcbm) cmd;
if (oicbm.getMessageType() == OldIcbm.MTYPE_PLAIN) {
String uin = String.valueOf(oicbm.getSender());
InstantMessage message = oicbm.getMessage();
String msg = StringUtils.unescapeFromXML(OscarTools.stripHtml(message.getMessage()));
oscarSession.getTransport().sendMessage(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(uin),
msg
);
}
}
else if (cmd instanceof WarningNotification) {
WarningNotification wn = (WarningNotification) cmd;
MiniUserInfo warner = wn.getWarner();
if (warner == null) {
oscarSession.getTransport().sendMessage(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.aim.warninganon", "gateway", Arrays.asList(wn.getNewLevel().toString())),
Message.Type.headline
);
}
else {
Log.debug("*** " + warner.getScreenname()
+ " warned you up to " + wn.getNewLevel() + "%");
oscarSession.getTransport().sendMessage(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.aim.warningdirect", "gateway", Arrays.asList(warner.getScreenname(), wn.getNewLevel().toString())),
Message.Type.headline
);
}
}
else if (cmd instanceof BuddyStatusCmd) {
BuddyStatusCmd bsc = (BuddyStatusCmd)cmd;
FullUserInfo info = bsc.getUserInfo();
buddystore.put(info.getScreenname(), info);
Presence p = new Presence();
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(info.getScreenname()));
if (info.getAwayStatus()) {
p.setShow(Presence.Show.away);
}
List<ExtraInfoBlock> extraInfo = info.getExtraInfoBlocks();
if (extraInfo != null) {
for (ExtraInfoBlock i : extraInfo) {
ExtraInfoData data = i.getExtraData();
if (i.getType() == ExtraInfoBlock.TYPE_AVAILMSG) {
String msg = ExtraInfoData.readAvailableMessage(data);
if (msg.length() > 0) {
p.setStatus(msg);
}
}
}
}
oscarSession.getTransport().sendPacket(p);
}
else if (cmd instanceof BuddyOfflineCmd) {
BuddyOfflineCmd boc = (BuddyOfflineCmd)cmd;
buddystore.remove(boc.getScreenname());
Presence p = new Presence(Presence.Type.unavailable);
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(boc.getScreenname()));
oscarSession.getTransport().sendPacket(p);
}
else if (cmd instanceof TypingCmd) {
TypingCmd tc = (TypingCmd) cmd;
String sn = tc.getScreenname();
if (tc.getTypingState() == TypingCmd.STATE_TYPING) {
oscarSession.getTransport().sendComposingNotification(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(sn)
);
}
else if (tc.getTypingState() == TypingCmd.STATE_PAUSED) {
oscarSession.getTransport().sendComposingPausedNotification(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(sn)
);
}
else if (tc.getTypingState() == TypingCmd.STATE_NO_TEXT) {
oscarSession.getTransport().sendChatInactiveNotification(
oscarSession.getJIDWithHighestPriority(),
oscarSession.getTransport().convertIDToJID(sn)
);
}
}
}
protected void handleSnacResponse(SnacResponseEvent e) {
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof RateInfoCmd) {
RateInfoCmd ric = (RateInfoCmd) cmd;
List <RateClassInfo> rateClasses = ric.getRateClassInfos();
int[] classes = new int[rateClasses.size()];
for (int i = 0; i < rateClasses.size(); i++) {
classes[i] = rateClasses.get(i).getRateClass();
}
request(new RateAck(classes));
}
}
public int[] getSnacFamilies() { return snacFamilies; }
protected void setSnacFamilies(int[] families) {
this.snacFamilies = families.clone();
Arrays.sort(snacFamilies);
}
protected void setSnacFamilyInfos(Collection<SnacFamilyInfo> infos) {
snacFamilyInfos = infos;
}
protected boolean supportsFamily(int family) {
return Arrays.binarySearch(snacFamilies, family) >= 0;
}
protected void clientReady() {
if (!sentClientReady) {
sentClientReady = true;
request(new ClientReadyCmd(snacFamilyInfos));
}
}
protected SnacRequest dispatchRequest(SnacCommand cmd) {
return dispatchRequest(cmd, null);
}
protected SnacRequest dispatchRequest(SnacCommand cmd,
SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
dispatchRequest(req);
return req;
}
protected void dispatchRequest(SnacRequest req) {
oscarSession.handleRequest(req);
}
protected SnacRequest request(SnacCommand cmd,
SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
handleReq(req);
return req;
}
private void handleReq(SnacRequest request) {
int family = request.getCommand().getFamily();
if (snacFamilies == null || supportsFamily(family)) {
// this connection supports this snac, so we'll send it here
sendRequest(request);
}
else {
oscarSession.handleRequest(request);
}
}
/**
* Retrieves and sends last known status.
*
* This retrieves the last known status of the user and sends it on
* to the JID associated with this session. Meant for probe packets.
*
* @param sn Screen name to check on.
*/
public void getAndSendStatus(String sn) {
if (buddystore.containsKey(sn)) {
FullUserInfo info = buddystore.get(sn);
buddystore.put(info.getScreenname(), info);
Presence p = new Presence();
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(info.getScreenname()));
if (info.getAwayStatus()) {
p.setShow(Presence.Show.away);
}
List<ExtraInfoBlock> extraInfo = info.getExtraInfoBlocks();
if (extraInfo != null) {
for (ExtraInfoBlock i : extraInfo) {
ExtraInfoData data = i.getExtraData();
if (i.getType() == ExtraInfoBlock.TYPE_AVAILMSG) {
ByteBlock msgBlock = data.getData();
int len = BinaryTools.getUShort(msgBlock, 0);
byte[] msgBytes = msgBlock.subBlock(2, len).toByteArray(
);
String msg;
try {
msg = new String(msgBytes, "UTF-8");
}
catch (UnsupportedEncodingException e1) {
continue;
}
if (msg.length() > 0) {
p.setStatus(msg);
}
}
}
}
oscarSession.getTransport().sendPacket(p);
}
else {
Presence p = new Presence();
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(sn));
p.setError(PacketError.Condition.forbidden);
oscarSession.getTransport().sendPacket(p);
}
}
/**
* Retrieves and sends last known status for all buddies.
*
* This retrieves all known statuses and sends each one of them to the specified JID.
* This is typically used when a new resource comes online.
*
* @param jid JID (with resource) to send the list to.
*/
public void getAndSendAllStatuses(JID jid) {
for (FullUserInfo info : buddystore.values()) {
buddystore.put(info.getScreenname(), info);
Presence p = new Presence();
p.setTo(oscarSession.getJID());
p.setFrom(oscarSession.getTransport().convertIDToJID(info.getScreenname()));
if (info.getAwayStatus()) {
p.setShow(Presence.Show.away);
}
List<ExtraInfoBlock> extraInfo = info.getExtraInfoBlocks();
if (extraInfo != null) {
for (ExtraInfoBlock i : extraInfo) {
ExtraInfoData data = i.getExtraData();
if (i.getType() == ExtraInfoBlock.TYPE_AVAILMSG) {
ByteBlock msgBlock = data.getData();
int len = BinaryTools.getUShort(msgBlock, 0);
byte[] msgBytes = msgBlock.subBlock(2, len).toByteArray(
);
String msg;
try {
msg = new String(msgBytes, "UTF-8");
}
catch (UnsupportedEncodingException e1) {
continue;
}
if (msg.length() > 0) {
p.setStatus(msg);
}
}
}
}
oscarSession.getTransport().sendPacket(p);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.jivesoftware.openfire.gateway.TransportType;
import org.xmpp.packet.Message;
import net.kano.joscar.*;
import net.kano.joscar.flap.*;
import net.kano.joscar.flapcmd.*;
import net.kano.joscar.net.*;
import net.kano.joscar.snac.*;
import net.kano.joscar.snaccmd.auth.*;
import java.util.Locale;
import java.util.Arrays;
/**
* Handles the login process with the OSCAR login server.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public class LoginConnection extends BaseFlapConnection {
public LoginConnection(ConnDescriptor cd, OSCARSession mainSession) {
super(cd, mainSession); // Hand off to BaseFlapConnection
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("OSCAR login service state change from "+e.getOldState()+" to "+e.getNewState());
if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
// if (getMainSession().getTransport().getType().equals(TransportType.icq)) {
// Log.debug("FINDME: Doing ICQ normal auth.");
// ClientVersionInfo version = new ClientVersionInfo(
// "ICQBasic",
// 0x010a, 0x0014, 0x0022, 0, 0x0911, 0x0000043d);
// String password = oscarSession.getRegistration().getPassword();
// // ICQ caps passwords at 8 characters.
// if (password.length() > 8) {
// password = password.substring(0, 8);
// }
// getFlapProcessor().sendFlap(new LoginICQFlapCmd(oscarSession.getRegistration().getUsername(), password, version, Locale.US));
// }
// else {
getFlapProcessor().sendFlap(new LoginFlapCmd());
request(new KeyRequest(oscarSession.getRegistration().getUsername()));
// }
}
else if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
Message m = new Message();
m.setType(Message.Type.error);
m.setFrom(this.getMainSession().getTransport().getJID());
m.setTo(this.getMainSession().getJIDWithHighestPriority());
m.setBody(LocaleUtils.getLocalizedString("gateway.oscar.connectionfailed", "gateway")+" " + e.getReason());
getMainSession().getTransport().sendPacket(m);
getMainSession().sessionDisconnected();
}
else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
//TODO: Do we need to catch these?
// if (!loggedin) {
// Message m = new Message();
// m.setType(Message.Type.error);
// m.setFrom(this.getMainSession().getTransport().getJID());
// m.setTo(this.getMainSession().getJIDWithHighestPriority());
// m.setBody("Connection lost: " + e.getReason());
// this.getMainSession().getTransport().sendPacket(m);
// this.getMainSession().logOut();
// }
}
}
protected void handleFlapPacket(FlapPacketEvent e) {
// FlapCommand cmd = e.getFlapCommand();
}
protected void handleSnacPacket(SnacPacketEvent e) { }
protected void handleSnacResponse(SnacResponseEvent e) {
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof KeyResponse) {
Log.debug("Handling AIM-style auth.");
KeyResponse kr = (KeyResponse) cmd;
ByteBlock authkey = kr.getKey();
ClientVersionInfo version = new ClientVersionInfo(
"AOL Instant Messenger, version 5.5.3415/WIN32",
-1, 5, 5, 0, 3415, 239);
String pass = oscarSession.getRegistration().getPassword();
if (oscarSession.getTransport().getType().equals(TransportType.icq)) {
if (pass.length() > 8) {
pass = pass.substring(0,8);
}
}
request(new AuthRequest(oscarSession.getRegistration().getUsername(), pass, version, Locale.US, authkey));
}
else if (cmd instanceof AuthResponse) {
Log.debug("Got auth response!");
AuthResponse ar = (AuthResponse) cmd;
int error = ar.getErrorCode();
if (error != -1) {
String errormsg;
switch (error) {
case (AuthResponse.ERROR_ACCOUNT_DELETED): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.accountdeleted", "gateway");
break;
}
case (AuthResponse.ERROR_BAD_INPUT): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.badinput", "gateway");
break;
}
case (AuthResponse.ERROR_BAD_PASSWORD): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.badpassword", "gateway");
break;
}
case (AuthResponse.ERROR_CLIENT_TOO_OLD): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.oldclient", "gateway");
break;
}
case (AuthResponse.ERROR_CONNECTING_TOO_MUCH_A):
case (AuthResponse.ERROR_CONNECTING_TOO_MUCH_B): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.connectedtoomuch", "gateway");
break;
}
case (AuthResponse.ERROR_INVALID_SN_OR_PASS_A):
case (AuthResponse.ERROR_INVALID_SN_OR_PASS_B): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.baduserorpass", "gateway");
break;
}
case (AuthResponse.ERROR_SIGNON_BLOCKED): {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.accountsuspended", "gateway");
break;
}
default: {
errormsg = LocaleUtils.getLocalizedString("gateway.oscar.unknownerror", "gateway", Arrays.asList(error, ar.getErrorUrl()));
}
}
Message m = new Message();
m.setType(Message.Type.error);
m.setTo(getMainSession().getJID());
m.setFrom(getMainSession().getTransport().getJID());
m.setBody(errormsg);
getMainSession().getTransport().sendPacket(m);
getMainSession().sessionDisconnectedNoReconnect();
}
else {
Log.debug("Got something else?");
getMainSession().setLoginStatus(TransportLoginStatus.LOGGED_IN);
oscarSession.startBosConn(ar.getServer(), ar.getPort(), ar.getCookie());
Log.info("OSCAR connection to " + ar.getServer() + ":"
+ ar.getPort());
}
disconnect();
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.ByteBlock;
import net.kano.joscar.BinaryTools;
import net.kano.joscar.DefensiveTools;
import net.kano.joscar.flap.FlapCommand;
import net.kano.joscar.snaccmd.auth.ClientVersionInfo;
import net.kano.joscar.tlv.Tlv;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import org.jivesoftware.util.Log;
/**
* Representation of an ICQ auth request.
*
* @author Daniel Henninger
* Heavily inspired by AuthRequest.java from the joscar project.
*/
public class LoginICQFlapCmd extends FlapCommand {
/**
* The FLAP channel on which this command resides.
*/
public static final int CHANNEL_LOGIN = 0x0001;
/**
* I guess this is the FLAP protocol version joscar implements; this is
* what should be sent in a FLAP version command. <code>1</code> is the only
* publically known FLAP protocol version.
*/
public static final long VERSION_DEFAULT = 0x00000001;
/**
* The type of the TLV that contains the cookie block.
*/
private static final int TYPE_COOKIE = 0x0006;
/**
* The version of the FLAP protocol in use.
*/
private final long version;
/**
* The connection cookie.
*/
private final ByteBlock cookie;
/** A TLV type containing the user's uin. */
private static final int TYPE_UIN = 0x0001;
/** A TLV type containing the user's two-letter country code. */
private static final int TYPE_COUNTRY = 0x000e;
/** A TLV type containing the user's two-letter language code. */
private static final int TYPE_LANG = 0x000f;
/** A TLV type containing the user's password, xored. */
private static final int TYPE_XORPASS = 0x0002;
/** The user's UIN (user identification number). */
private final String uin;
/** The user's client version information. */
private final ClientVersionInfo clVersion;
/** The user's locale. */
private final Locale locale;
/** The user's password, encrypted. */
private final ByteBlock encryptedPass;
/**
* Creates a <code>LoginCookieCmd</code> with the {@linkplain
* #VERSION_DEFAULT default FLAP version} and no login cookie.
* @param uin UIN of the username logging in
* @param pass Password of the user logging in
* @param clVersion version for the ICQ client
* @param locale Locale for the connection.
*/
public LoginICQFlapCmd(String uin, String pass, ClientVersionInfo clVersion, Locale locale) {
this(VERSION_DEFAULT, null, uin, pass, clVersion, locale);
}
/**
* Creates a <code>LoginCookieCmd</code> with the given FLAP version and
* no login cookie. This constructor is useful for server developers because
* no login cookie is ever sent by the server; also, no login cookie is sent
* by the client or the server upon initial connection to the login ("auth")
* server.
*
* @param version the FLAP protocol version in use on the FLAP connection on
* which this command will be sent
* @param uin UIN of the username logging in
* @param pass Password of the user logging in
* @param clVersion version for the ICQ client
* @param locale Locale for the connection.
*/
public LoginICQFlapCmd(long version, String uin, String pass, ClientVersionInfo clVersion, Locale locale) {
this(version, null, uin, pass, clVersion, locale);
}
/**
* Creates a <code>LoginCookieCmd</code> with the {@linkplain
* #VERSION_DEFAULT default FLAP version} and the given login cookie.
*
* @param cookie the login cookie for the connection on which this command
* will be sent
* @param uin UIN of the username logging in
* @param pass Password of the user logging in
* @param clVersion version for the ICQ client
* @param locale Locale for the connection.
*/
public LoginICQFlapCmd(ByteBlock cookie, String uin, String pass, ClientVersionInfo clVersion, Locale locale) {
this(VERSION_DEFAULT, cookie, uin, pass, clVersion, locale);
}
/**
* Creates a new <code>LoginCookieCmd</code> with the given FLAP protocol
* version and with the given cookie.
*
* @param version the FLAP protocol version in use
* @param cookie a login "cookie" provided by another OSCAR connection
* @param uin UIN of the username logging in
* @param pass Password of the user logging in
* @param clVersion version for the ICQ client
* @param locale Locale for the connection.
*/
public LoginICQFlapCmd(long version, ByteBlock cookie, String uin, String pass, ClientVersionInfo clVersion, Locale locale) {
super(CHANNEL_LOGIN);
DefensiveTools.checkRange(version, "version", 0);
this.version = version;
this.cookie = cookie;
this.uin = uin;
this.clVersion = clVersion;
this.locale = locale;
this.encryptedPass = ByteBlock.wrap(encryptICQPassword(pass));
Log.debug("Non-encrypted password is "+pass+", Encrypted password is "+encryptedPass);
}
/**
* Encrypts the given password with ICQ's xor key.
* This code is borrowed from JOscarLib (http://sourceforge.net/projects/ooimlib/)
*
* @param pass the user's password
* @return the user's password, encrypted
*/
private byte[] encryptICQPassword(String pass) {
//char charPass[] = new char[pass.length()];
byte encPass[] = new byte[pass.length()];
byte bytePassword[] = pass.getBytes();
final byte[] xorValues = {
(byte) 0xF3, (byte) 0x26, (byte) 0x81, (byte) 0xC4,
(byte) 0x39, (byte) 0x86, (byte) 0xDB, (byte) 0x92
};
for (int i = 0, j; i < bytePassword.length; i++) {
j = i % xorValues.length;
//charPass[i] = (char) ( (byte) (bytePassword[i]) ^ (byte) (xorValues[j]));
encPass[i] = (byte)((bytePassword[i]) ^ (xorValues[j]));
}
return encPass;
}
/**
* Returns the UIN whose login is being attempted.
*
* @return the user's UIN
*/
public final String getUIN() { return uin; }
/**
* Returns the user's client information block.
*
* @return the user's client version information
*/
public final ClientVersionInfo getVersionInfo() { return clVersion; }
/**
* Returns the user's locale.
*
* @return the user's locale
*/
public final Locale getLocale() { return locale; }
/**
* The raw encrypted password sent in this authorization request.
*
* @return the user's password, encrypted
*/
public final ByteBlock getEncryptedPass() { return encryptedPass; }
/**
* Returns the FLAP protocol version declared in this command.
*
* @return the FLAP version of the FLAP connection on which this packet was
* received
*/
public final long getVersion() { return version; }
/**
* Returns the login cookie associated with this command.
*
* @return this command's login cookie
*/
public final ByteBlock getCookie() { return cookie; }
public void writeData(OutputStream out) throws IOException {
BinaryTools.writeUInt(out, version);
if (cookie != null) new Tlv(TYPE_COOKIE, cookie).write(out);
if (uin != null) {
Tlv.getStringInstance(TYPE_UIN, uin).write(out);
}
if (encryptedPass != null) {
new Tlv(TYPE_XORPASS, encryptedPass).write(out);
}
// write the version TLV's
if (clVersion != null) clVersion.write(out);
if (locale != null) {
String language = locale.getLanguage();
if (!language.equals("")) {
Tlv.getStringInstance(TYPE_LANG, language).write(out);
}
String country = locale.getCountry();
if (!country.equals("")) {
Tlv.getStringInstance(TYPE_COUNTRY, country).write(out);
}
}
}
public String toString() {
return "LoginICQFlapCmd: "
+ "version=" + version
+ ", cookie=" + cookie + ", uin='" + uin + "'" +
", version='" + version + "'" + ", locale=" + locale;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import net.kano.joscar.ByteBlock;
import net.kano.joscar.OscarTools;
import net.kano.joscar.SeqNum;
import net.kano.joscar.net.ConnDescriptor;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.snac.SnacRequest;
import net.kano.joscar.snac.SnacRequestListener;
import net.kano.joscar.snaccmd.ssi.CreateItemsCmd;
import net.kano.joscar.snaccmd.ssi.DeleteItemsCmd;
import net.kano.joscar.snaccmd.ssi.ModifyItemsCmd;
import net.kano.joscar.snaccmd.icbm.SendImIcbm;
import net.kano.joscar.snaccmd.icbm.SendTypingNotification;
import net.kano.joscar.snaccmd.conn.ServiceRequest;
import net.kano.joscar.snaccmd.loc.SetInfoCmd;
import net.kano.joscar.snaccmd.InfoData;
import net.kano.joscar.snaccmd.CapabilityBlock;
import net.kano.joscar.snaccmd.icq.OfflineMsgIcqRequest;
import net.kano.joscar.ssiitem.BuddyItem;
import net.kano.joscar.ssiitem.GroupItem;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.roster.RosterItem;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.xmpp.packet.Message;
import org.xmpp.packet.PacketError;
/**
* Represents an OSCAR session.
*
* This is the interface with which the base transport functionality will
* communicate with OSCAR (AIM/ICQ).
*
* Yeesh, this is the one I'm most familiar with and yet it's the ugliest.
* This needs some housecleaning.
*
* @author Daniel Henninger
*/
public class OSCARSession extends TransportSession {
/**
* Initialize a new session object for OSCAR
*
* @param registration The registration information to use during login.
* @param jid The JID associated with this session.
* @param transport The transport that created this session.
* @param priority Priority of this session.
*/
public OSCARSession(Registration registration, JID jid, OSCARTransport transport, Integer priority) {
super(registration, jid, transport, priority);
this.propertyPrefix = "plugin.gateway."+transport.getType().toString();
OscarTools.setDefaultCharset(JiveGlobals.getProperty(this.propertyPrefix+".encoding", "ISO8859-1"));
highestBuddyIdPerGroup.put(0, 0); // Main group highest id
}
private BOSConnection bosConn = null;
private LoginConnection loginConn = null;
private Set<ServiceConnection> services = new HashSet<ServiceConnection>();
private PresenceType presenceType = null;
private String verboseStatus = null;
private String propertyPrefix;
private static final String DEFAULT_AIM_GROUP = " "; // We're using 3 spaces to indicated main group, invalid in real aim
private static final String DEFAULT_ICQ_GROUP = "General";
private SeqNum icqSeqNum = new SeqNum(0, Integer.MAX_VALUE);
/**
* SSI tracking variables.
*/
private ConcurrentHashMap<String, BuddyItem> buddies = new ConcurrentHashMap<String,BuddyItem>();
private ConcurrentHashMap<Integer, GroupItem> groups = new ConcurrentHashMap<Integer,GroupItem>();
private ConcurrentHashMap<Integer,Integer> highestBuddyIdPerGroup = new ConcurrentHashMap<Integer,Integer>();
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!isLoggedIn()) {
loginConn = new LoginConnection(new ConnDescriptor(
JiveGlobals.getProperty(propertyPrefix+".connecthost", "login.oscar.aol.com"),
JiveGlobals.getIntProperty(propertyPrefix+".connectport", 5190)),
this);
loginConn.connect();
this.presenceType = presenceType;
this.verboseStatus = verboseStatus;
}
else {
Log.warn(this.jid + " is already logged in");
}
}
public synchronized void logOut() {
cleanUp();
sessionDisconnectedNoReconnect();
}
public synchronized void cleanUp() {
if (loginConn != null) {
loginConn.disconnect();
loginConn = null;
}
if (bosConn != null) {
bosConn.disconnect();
bosConn = null;
}
for (ServiceConnection conn : getServiceConnections()) {
try {
conn.disconnect();
}
catch (Exception e) {
// Ignore.
}
try {
services.remove(conn);
}
catch (Exception e) {
// Ignore.
}
try {
snacMgr.unregister(conn);
}
catch (Exception e) {
// Ignore.
}
}
}
/**
* Finds the id number of a group specified or creates a new one and returns that id.
*
* @param groupName Name of the group we are looking for.
* @return Id number of the group.
*/
public Integer getGroupIdOrCreateNew(String groupName) {
if (groupName.matches("/^\\s*$/")) { return 0; } // Special master group handling
for (GroupItem g : groups.values()) {
if (groupName.equalsIgnoreCase(g.getGroupName())) {
return g.getId();
}
}
// Group doesn't exist, lets create a new one.
Integer newGroupId = highestBuddyIdPerGroup.get(0) + 1;
GroupItem newGroup = new GroupItem(groupName, newGroupId);
request(new CreateItemsCmd(newGroup.toSsiItem()));
gotGroup(newGroup);
return newGroupId;
}
/**
* Synchronizes the list of groups a contact is a member of, updating nicknames in
* the process.
*
* @param contact Screen name/UIN of the contact.
* @param nickname Nickname of the contact (should not be null)
* @param grouplist List of groups the contact should be a member of.
*/
public void syncContactGroupsAndNickname(String contact, String nickname, List<String> grouplist) {
if (grouplist.isEmpty()) {
if (transport.getType().equals(TransportType.icq)) {
grouplist.add(DEFAULT_ICQ_GROUP);
}
else {
grouplist.add(DEFAULT_AIM_GROUP);
}
}
Log.debug("contact = "+contact+", grouplist = "+grouplist);
// First, lets take the known good list of groups and add whatever is missing on the server.
for (String group : grouplist) {
Integer groupId = getGroupIdOrCreateNew(group);
Integer newBuddyId = 1;
if (highestBuddyIdPerGroup.containsKey(groupId)) {
newBuddyId = highestBuddyIdPerGroup.get(groupId) + 1;
}
BuddyItem newBuddy = new BuddyItem(contact, groupId, newBuddyId);
newBuddy.setAlias(nickname);
request(new CreateItemsCmd(newBuddy.toSsiItem()));
gotBuddy(newBuddy);
}
// Now, lets clean up any groups this contact should no longer be a member of.
for (BuddyItem buddy : buddies.values()) {
if (buddy.getScreenname().equalsIgnoreCase(contact)) {
if (buddy.getGroupId() == 0 && !grouplist.contains(DEFAULT_AIM_GROUP)) {
// Ok this group is the "main group", but contact isn't in it.
Log.debug("Removing "+buddy+" from main group");
request(new DeleteItemsCmd(buddy.toSsiItem()));
buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
}
else if (!groups.containsKey(buddy.getGroupId())) {
// Well this is odd, a group we don't know about? Nuke it.
Log.debug("Removing "+buddy+" because of unknown group");
request(new DeleteItemsCmd(buddy.toSsiItem()));
buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
}
else if (!grouplist.contains(groups.get(buddy.getGroupId()).getGroupName())) {
Log.debug("Removing "+buddy+" because not in list of groups");
request(new DeleteItemsCmd(buddy.toSsiItem()));
buddies.remove(""+buddy.getGroupId()+"."+buddy.getId());
}
else {
if (buddy.getAlias() == null || !buddy.getAlias().equals(nickname)) {
buddy.setAlias(nickname);
request(new ModifyItemsCmd(buddy.toSsiItem()));
}
}
}
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#addContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void addContact(RosterItem item) {
String legacyId = getTransport().convertJIDToID(item.getJid());
String nickname = item.getNickname();
if (nickname == null || nickname.equals("")) {
nickname = legacyId;
}
// Syncing takes care of all the dirty work.
lockRoster(item.getJid().toString());
syncContactGroupsAndNickname(legacyId, nickname, item.getGroups());
unlockRoster(item.getJid().toString());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#removeContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void removeContact(RosterItem item) {
String legacyId = getTransport().convertJIDToID(item.getJid());
for (BuddyItem i : buddies.values()) {
if (i.getScreenname().equalsIgnoreCase(legacyId)) {
lockRoster(item.getJid().toString());
request(new DeleteItemsCmd(i.toSsiItem()));
buddies.remove(""+i.getGroupId()+"."+i.getId());
unlockRoster(item.getJid().toString());
}
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void updateContact(RosterItem item) {
String legacyId = getTransport().convertJIDToID(item.getJid());
String nickname = item.getNickname();
if (nickname == null || nickname.equals("")) {
nickname = legacyId;
}
// Syncing takes care of all of the dirty work.
lockRoster(item.getJid().toString());
syncContactGroupsAndNickname(legacyId, nickname, item.getGroups());
unlockRoster(item.getJid().toString());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendMessage(org.xmpp.packet.JID, String)
*/
public void sendMessage(JID jid, String message) {
request(new SendImIcbm(getTransport().convertJIDToID(jid), message));
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendServerMessage(String)
*/
public void sendServerMessage(String message) {
// We don't care.
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendChatState(org.xmpp.packet.JID, org.jivesoftware.openfire.gateway.ChatStateType)
*/
public void sendChatState(JID jid, ChatStateType chatState) {
if (chatState.equals(ChatStateType.composing)) {
request(new SendTypingNotification(
getTransport().convertJIDToID(jid),
SendTypingNotification.STATE_TYPING
));
}
else if (chatState.equals(ChatStateType.paused)) {
request(new SendTypingNotification(
getTransport().convertJIDToID(jid),
SendTypingNotification.STATE_PAUSED
));
}
else if (chatState.equals(ChatStateType.inactive)) {
request(new SendTypingNotification(
getTransport().convertJIDToID(jid),
SendTypingNotification.STATE_NO_TEXT
));
}
}
/**
* Opens/creates a new BOS connection to a specific server and port, given a cookie.
*
* @param server Server to connect to.
* @param port Port to connect to.
* @param cookie Auth cookie.
*/
void startBosConn(String server, int port, ByteBlock cookie) {
bosConn = new BOSConnection(new ConnDescriptor(server, port), this, cookie);
bosConn.connect();
}
/**
* Registers the set of SNAC families that the given connection supports.
*
* @param conn FLAP connection to be registered.
*/
void registerSnacFamilies(BasicFlapConnection conn) {
snacMgr.register(conn);
}
protected SnacManager snacMgr = new SnacManager(new PendingSnacListener() {
public void dequeueSnacs(List<SnacRequest> pending) {
for (SnacRequest request : pending) {
handleRequest(request);
}
}
});
synchronized void handleRequest(SnacRequest request) {
int family = request.getCommand().getFamily();
if (snacMgr.isPending(family)) {
snacMgr.addRequest(request);
return;
}
BasicFlapConnection conn = snacMgr.getConn(family);
if (conn != null) {
conn.sendRequest(request);
}
else {
// it's time to request a service
if (!(request.getCommand() instanceof ServiceRequest)) {
snacMgr.setPending(family, true);
snacMgr.addRequest(request);
request(new ServiceRequest(family));
} else {
// TODO: Why does this occur a lot and yet not cause problems?
// Log.error("eep! can't find a service redirector server.");
}
}
}
SnacRequest request(SnacCommand cmd) {
return request(cmd, null);
}
private SnacRequest request(SnacCommand cmd, SnacRequestListener listener) {
SnacRequest req = new SnacRequest(cmd, listener);
handleRequest(req);
return req;
}
void connectToService(int snacFamily, String host, ByteBlock cookie) {
ServiceConnection conn = new ServiceConnection(new ConnDescriptor(host,
JiveGlobals.getIntProperty(propertyPrefix+".connectport", 5190)),
this,
cookie,
snacFamily);
conn.connect();
}
void serviceFailed(ServiceConnection conn) {
Log.debug("OSCAR service failed: "+conn.toString());
}
void serviceConnected(ServiceConnection conn) {
Log.debug("OSCAR service connected: "+conn.toString());
services.add(conn);
}
public boolean isServiceConnected(ServiceConnection conn) {
return services.contains(conn);
}
public Set<ServiceConnection> getServiceConnections() {
return services;
}
void serviceReady(ServiceConnection conn) {
Log.debug("OSCAR service ready: "+conn.toString());
snacMgr.dequeueSnacs(conn);
}
void serviceDied(ServiceConnection conn) {
Log.debug("OSCAR service died: "+conn.toString());
services.remove(conn);
snacMgr.unregister(conn);
}
void bosDisconnected() {
Message m = new Message();
m.setType(Message.Type.error);
m.setError(PacketError.Condition.internal_server_error);
m.setTo(getJID());
m.setFrom(getTransport().getJID());
m.setBody(LocaleUtils.getLocalizedString("gateway.oscar.disconnected", "gateway"));
getTransport().sendPacket(m);
sessionDisconnected();
}
/**
* We've been told about a buddy that exists on the buddy list.
*
* @param buddy The buddy we've been told about.
*/
void gotBuddy(BuddyItem buddy) {
Log.debug("Found buddy item: " + buddy.toString() + " at id " + buddy.getId());
buddies.put(""+buddy.getGroupId()+"."+buddy.getId(), buddy);
if (!highestBuddyIdPerGroup.containsKey(buddy.getGroupId())) {
highestBuddyIdPerGroup.put(buddy.getGroupId(), 0);
}
if (buddy.getId() > highestBuddyIdPerGroup.get(buddy.getGroupId())) {
highestBuddyIdPerGroup.put(buddy.getGroupId(), buddy.getId());
}
}
/**
* We've been told about a group that exists on the buddy list.
*
* @param group The group we've been told about.
*/
void gotGroup(GroupItem group) {
Log.debug("Found group item: " + group.toString() + " at id " + group.getId());
groups.put(group.getId(), group);
if (!highestBuddyIdPerGroup.containsKey(0)) {
highestBuddyIdPerGroup.put(0, 0);
}
if (group.getId() > highestBuddyIdPerGroup.get(0)) {
highestBuddyIdPerGroup.put(0, group.getId());
}
}
/**
* Apparantly we now have the entire list, lets sync.
*/
void gotCompleteSSI() {
getRegistration().setLastLogin(new Date());
List<TransportBuddy> legacyusers = new ArrayList<TransportBuddy>();
for (BuddyItem buddy : buddies.values()) {
//Log.debug("CompleteSSI: adding "+buddy.getScreenname());
String nickname = buddy.getAlias();
if (nickname == null || nickname.matches("/^\\s*$/")) {
nickname = buddy.getScreenname();
}
// Doesn't work yet so disabling.
// try {
// if (nickname.equalsIgnoreCase(buddy.getScreenname())) {
// Integer buddyUIN = Integer.parseInt(buddy.getScreenname());
// Log.debug("REQUESTING SHORT INFO FOR "+buddyUIN);
// request(new MetaFullInfoRequest(getUIN(), (int)nextIcqId(), buddyUIN));
// }
// }
// catch (NumberFormatException e) {
// // Not an ICQ number then ;D
// }
if (nickname == null) {
nickname = buddy.getScreenname();
}
int groupid = buddy.getGroupId();
String groupname = null;
if (groupid != 0 && groups.containsKey(groupid)) {
String newgroupname = groups.get(groupid).getGroupName();
if (newgroupname.length() > 0) {
groupname = newgroupname;
}
}
legacyusers.add(new TransportBuddy(buddy.getScreenname(), nickname, groupname));
}
try {
getTransport().syncLegacyRoster(getJID(), legacyusers);
}
catch (UserNotFoundException e) {
Log.error("Unable to sync oscar contact list for " + getJID(), e);
}
updateStatus(this.presenceType, this.verboseStatus);
if (getTransport().getType().equals(TransportType.icq)) {
request(new OfflineMsgIcqRequest(getUIN(), (int)nextIcqId()));
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#retrieveContactStatus(org.xmpp.packet.JID)
*/
public void retrieveContactStatus(JID jid) {
if (isLoggedIn()) {
if (bosConn != null) {
bosConn.getAndSendStatus(getTransport().convertJIDToID(jid));
}
}
}
private static final List<CapabilityBlock> MY_CAPS = Arrays.asList(
CapabilityBlock.BLOCK_ICQCOMPATIBLE
);
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateStatus(org.jivesoftware.openfire.gateway.PresenceType, String)
*/
public void updateStatus(PresenceType presenceType, String verboseStatus) {
if (presenceType != PresenceType.available && presenceType != PresenceType.chat) {
String awayMsg = LocaleUtils.getLocalizedString("gateway.oscar.away", "gateway");
if (verboseStatus != null) {
awayMsg = verboseStatus;
}
request(new SetInfoCmd(new InfoData(null, awayMsg, MY_CAPS, null)));
Presence p = new Presence();
p.setShow(Presence.Show.away);
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
}
else {
request(new SetInfoCmd(new InfoData(null, InfoData.NOT_AWAY, MY_CAPS, null)));
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
}
this.presenceType = presenceType;
this.verboseStatus = verboseStatus;
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#resendContactStatuses(org.xmpp.packet.JID)
*/
public void resendContactStatuses(JID jid) {
if (bosConn != null) {
bosConn.getAndSendAllStatuses(jid);
}
}
/**
* Retrieves the next ICQ id number and increments the counter.
* @return The next ICQ id number.
*/
public long nextIcqId() { return icqSeqNum.next(); }
/**
* Retrieves a UIN in integer format for the session.
*
* @return The UIN in integer format.
*/
public int getUIN() {
try {
return Integer.parseInt(getRegistration().getUsername());
}
catch (Exception e) {
return -1;
}
}
/**
* Updates roster nickname information about a contact.
*
* @param sn Screenname/UIN of contact
* @param nickname New nickname
*/
public void updateRosterNickname(String sn, String nickname) {
BuddyItem buddy = buddies.get(sn);
if (buddy == null) { return; }
int groupid = buddy.getGroupId();
String groupname = null;
if (groupid != 0 && groups.containsKey(groupid)) {
String newgroupname = groups.get(groupid).getGroupName();
if (newgroupname.length() > 0) {
groupname = newgroupname;
}
}
try {
getTransport().addOrUpdateRosterItem(getJID(), getTransport().convertIDToJID(sn), nickname, groupname);
}
catch (UserNotFoundException e) {
Log.error("Contact not found while updating nickname.");
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
/**
* OSCAR Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class OSCARTransport extends BaseTransport {
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyUsername()
*/
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway."+getType().toString()+".username", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyPassword()
*/
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway."+getType().toString()+".password", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyNickname()
*/
public String getTerminologyNickname() {
return null;
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyRegistration()
*/
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway."+getType().toString()+".registration", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isPasswordRequired()
*/
public Boolean isPasswordRequired() { return true; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isNicknameRequired()
*/
public Boolean isNicknameRequired() { return false; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isUsernameValid(String)
*/
public Boolean isUsernameValid(String username) {
if (getType() == TransportType.icq) {
return username.matches("\\d+");
}
else {
return username.matches("\\w+") || username.matches("\\w+@[\\w\\.]+");
}
}
/**
* Handles creating an OSCAR session and triggering a login.
*
* @param registration Registration information to be used to log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new OSCARSession(registration, jid, this, priority);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
/**
* Handles logging out of a Yahoo session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.snac.SnacRequest;
import java.util.List;
/**
* Handles events from pending SNAC manager.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public interface PendingSnacListener {
void dequeueSnacs(List<SnacRequest> pending);
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.snac.SnacRequest;
import net.kano.joscar.DefensiveTools;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Handles pending SNAC commands.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public class PendingSnacMgr {
protected Map<Integer,List<SnacRequest>> snacs = new HashMap<Integer,List<SnacRequest>>();
public boolean isPending(int familyCode) {
return snacs.containsKey(familyCode);
}
public void add(SnacRequest request) {
Integer family = request.getCommand().getFamily();
List<SnacRequest> pending = snacs.get(family);
pending.add(request);
}
public List<SnacRequest> getPending(int familyCode) {
List<SnacRequest> pending = snacs.get(familyCode);
return DefensiveTools.getUnmodifiableCopy(pending);
}
public void setPending(int familyCode, boolean pending) {
if (pending) {
snacs.put(familyCode, new ArrayList<SnacRequest>());
}
else {
snacs.remove(familyCode);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.flap.ClientFlapConn;
import net.kano.joscar.flap.FlapPacketEvent;
import net.kano.joscar.ByteBlock;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.snaccmd.conn.RateInfoCmd;
import net.kano.joscar.snac.SnacPacketEvent;
import net.kano.joscar.snac.SnacResponseEvent;
import net.kano.joscar.net.ClientConnEvent;
import net.kano.joscar.net.ConnDescriptor;
import org.jivesoftware.util.Log;
/**
* Represents a connection to a particular OSCAR service.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public class ServiceConnection extends BasicFlapConnection {
protected int serviceFamily;
public ServiceConnection(ConnDescriptor cd, OSCARSession mainSession, ByteBlock cookie, int serviceFamily) {
super(cd, mainSession, cookie);
this.serviceFamily = serviceFamily;
}
protected void clientReady() {
oscarSession.serviceReady(this);
super.clientReady();
}
protected void handleStateChange(ClientConnEvent e) {
Log.debug("OSCAR service state change from "+e.getOldState()+" to "+e.getNewState());
if (e.getNewState() == ClientFlapConn.STATE_FAILED) {
oscarSession.serviceFailed(this);
} else if (e.getNewState() == ClientFlapConn.STATE_CONNECTED) {
oscarSession.serviceConnected(this);
} else if (e.getNewState() == ClientFlapConn.STATE_NOT_CONNECTED) {
oscarSession.serviceDied(this);
}
}
protected void handleFlapPacket(FlapPacketEvent e) {
super.handleFlapPacket(e);
}
protected void handleSnacPacket(SnacPacketEvent e) {
super.handleSnacPacket(e);
}
protected void handleSnacResponse(SnacResponseEvent e) {
super.handleSnacResponse(e);
SnacCommand cmd = e.getSnacCommand();
if (cmd instanceof RateInfoCmd) {
// this is all we need.
clientReady();
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*
* Heavily inspired by joscardemo of the Joust Project: http://joust.kano.net/
*/
package org.jivesoftware.openfire.gateway.protocols.oscar;
import net.kano.joscar.snac.SnacRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Handles incoming SNAC packets.
*
* @author Daniel Henninger
* Heavily inspired by joscardemo from the joscar project.
*/
public class SnacManager {
protected Map<Integer,List<BasicFlapConnection>> conns = new HashMap<Integer,List<BasicFlapConnection>>();
protected PendingSnacMgr pendingSnacs = new PendingSnacMgr();
protected List<PendingSnacListener> listeners = new ArrayList<PendingSnacListener>();
protected Map<BasicFlapConnection,int[]> supportedFamilies = new IdentityHashMap<BasicFlapConnection,int[]>();
public SnacManager() { }
public SnacManager(PendingSnacListener listener) {
addListener(listener);
}
public void register(BasicFlapConnection conn) {
int[] families = conn.getSnacFamilies();
supportedFamilies.put(conn, families);
for (int familyCode : families) {
List<BasicFlapConnection> handlers = conns.get(familyCode);
if (handlers == null) {
handlers = new LinkedList<BasicFlapConnection>();
conns.put(familyCode, handlers);
}
if (!handlers.contains(conn)) {
handlers.add(conn);
}
}
}
public void dequeueSnacs(BasicFlapConnection conn) {
int[] infos = supportedFamilies.get(conn);
if (infos != null) {
for (int familyCode : infos) {
if (pendingSnacs.isPending(familyCode)) {
dequeueSnacs(familyCode);
}
}
}
}
protected void dequeueSnacs(int familyCode) {
List<SnacRequest> pending = pendingSnacs.getPending(familyCode);
pendingSnacs.setPending(familyCode, false);
for (PendingSnacListener listener : listeners) {
listener.dequeueSnacs(pending);
}
}
public void unregister(BasicFlapConnection conn) {
for (List<BasicFlapConnection> handlers : conns.values()) {
handlers.remove(conn);
}
}
public BasicFlapConnection getConn(int familyCode) {
List<BasicFlapConnection> handlers = conns.get(familyCode);
if (handlers == null || handlers.size() == 0) {
return null;
}
return handlers.get(0);
}
public boolean isPending(int familyCode) {
return pendingSnacs.isPending(familyCode);
}
public void addRequest(SnacRequest request) {
int family = request.getCommand().getFamily();
if (!isPending(family)) {
throw new IllegalArgumentException("Family 0x"
+ Integer.toHexString(family) + " is not pending");
}
pendingSnacs.add(request);
}
public void addListener(PendingSnacListener l) {
if (!listeners.contains(l)) {
listeners.add(l);
}
}
public void removeListener(PendingSnacListener l) {
listeners.remove(l);
}
public void setPending(int family, boolean pending) {
pendingSnacs.setPending(family, pending);
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.xmpp;
import org.jivesoftware.smack.*;
import org.jivesoftware.util.Log;
import org.xmpp.packet.Presence;
import java.util.Collection;
/**
* Handles incoming events from XMPP server.
*
* @author Daniel Henninger
*/
public class XMPPListener implements MessageListener, RosterListener, ConnectionListener, ChatManagerListener {
/**
* Creates an XMPP listener instance and ties to session.
*
* @param session Session this listener is associated with.
*/
public XMPPListener(XMPPSession session) {
this.xmppSession = session;
}
/**
* Session instance that the listener is associated with.
*/
public XMPPSession xmppSession = null;
/**
* Handlings incoming messages.
*
* @param chat Chat instance this message is associated with.
* @param message Message received.
*/
public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
Log.debug("XMPP got message: "+message.toXML());
xmppSession.getTransport().sendMessage(
xmppSession.getJIDWithHighestPriority(),
xmppSession.getTransport().convertIDToJID(xmppSession.getBareJID(message.getFrom())),
message.getBody()
);
}
public void entriesAdded(Collection<String> collection) {
//Ignoring for now
}
public void entriesUpdated(Collection<String> collection) {
//Ignoring for now
}
public void entriesDeleted(Collection<String> collection) {
//Ignoring for now
}
public void presenceChanged(org.jivesoftware.smack.packet.Presence presence) {
Presence p = new Presence();
if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.available)) {
// Nothing to do
}
else if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.unavailable)) {
p.setType(Presence.Type.unavailable);
}
else if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.subscribe)) {
p.setType(Presence.Type.subscribe);
}
else if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.subscribed)) {
p.setType(Presence.Type.subscribed);
}
else if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.unsubscribe)) {
p.setType(Presence.Type.unsubscribe);
}
else if (presence.getType().equals(org.jivesoftware.smack.packet.Presence.Type.unsubscribed)) {
p.setType(Presence.Type.unsubscribed);
}
p.setTo(xmppSession.getJID());
p.setFrom(xmppSession.getTransport().convertIDToJID(xmppSession.getBareJID(presence.getFrom())));
xmppSession.getTransport().sendPacket(p);
}
public void connectionClosed() {
Presence p = new Presence();
p.setType(Presence.Type.unavailable);
p.setTo(xmppSession.getJID());
p.setFrom(xmppSession.getTransport().getJID());
xmppSession.getTransport().sendPacket(p);
}
public void connectionClosedOnError(Exception exception) {
xmppSession.getTransport().sendMessage(
xmppSession.getJIDWithHighestPriority(),
xmppSession.getTransport().getJID(),
"Conection closed."
);
Presence p = new Presence();
p.setType(Presence.Type.unavailable);
p.setTo(xmppSession.getJID());
p.setFrom(xmppSession.getTransport().getJID());
xmppSession.getTransport().sendPacket(p);
}
public void reconnectingIn(int i) {
//Ignoring for now
}
public void reconnectionSuccessful() {
//Ignoring for now
}
public void reconnectionFailed(Exception exception) {
//Ignoring for now
}
public void chatCreated(Chat chat, boolean b) {
//More or less can ignore this.
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.xmpp;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import java.util.Date;
/**
* Represents an XMPP session.
*
* This is the interface with which the base transport functionality will
* communicate with an XMPP server.
*
* @author Daniel Henninger
*/
public class XMPPSession extends TransportSession {
/**
* Create an XMPP Session instance.
*
* @param registration Registration informationed used for logging in.
* @param jid JID associated with this session.
* @param transport Transport instance associated with this session.
* @param priority Priority of this session.
*/
public XMPPSession(Registration registration, JID jid, XMPPTransport transport, Integer priority) {
super(registration, jid, transport, priority);
acctjid = new JID(registration.getUsername());
Log.debug("Creating "+getTransport().getType()+" session for " + registration.getUsername());
//XMPPConnection.DEBUG_ENABLED = true;
config = new ConnectionConfiguration(
JiveGlobals.getProperty("plugin.gateway."+getTransport().getType()+".connecthost",
(getTransport().getType().equals(TransportType.gtalk) ? "talk.google.com" : "jabber.org")),
JiveGlobals.getIntProperty("plugin.gateway."+getTransport().getType()+".connectport", 5222),
acctjid.getDomain());
config.setCompressionEnabled(false);
config.setReconnectionAllowed(false);
listener = new XMPPListener(this);
}
/*
* XMPP connection
*/
private XMPPConnection conn = null;
/**
* XMPP listener
*/
private XMPPListener listener = null;
/*
* XMPP connection configuration
*/
private ConnectionConfiguration config = null;
/**
* Accounts's jid associated with this session.
*/
private JID acctjid = null;
public void logIn(PresenceType presenceType, String verboseStatus) {
if (!isLoggedIn()) {
new Thread() {
public void run() {
try {
conn = new XMPPConnection(config);
conn.connect();
conn.addConnectionListener(listener);
conn.login(acctjid.getNode(), getRegistration().getPassword(), "IMGateway");
conn.getRoster().addRosterListener(listener);
conn.getChatManager().addChatListener(listener);
setLoginStatus(TransportLoginStatus.LOGGED_IN);
Presence p = new Presence();
p.setTo(getJIDWithHighestPriority());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
getRegistration().setLastLogin(new Date());
}
catch (XMPPException e) {
Log.error(getTransport().getType()+" user is not able to log in: "+getRegistration().getUsername(), e);
}
}
}.start();
}
}
public void logOut() {
cleanUp();
sessionDisconnectedNoReconnect();
}
public void cleanUp() {
conn.removeConnectionListener(listener);
conn.getRoster().removeRosterListener(listener);
conn.getChatManager().removeChatListener(listener);
conn.disconnect();
}
public void updateStatus(PresenceType presenceType, String verboseStatus) {
}
public void addContact(RosterItem item) {
}
public void removeContact(RosterItem item) {
}
public void updateContact(RosterItem item) {
}
public void sendMessage(JID jid, String message) {
org.jivesoftware.smack.packet.Message m = new org.jivesoftware.smack.packet.Message();
m.setFrom(getRegistration().getUsername());
m.setTo(getTransport().convertJIDToID(jid));
m.setBody(message);
Log.debug("XMPP Sending Message: "+m.toXML());
conn.sendPacket(m);
}
public void sendServerMessage(String message) {
//Don't care
}
public void sendChatState(JID jid, ChatStateType chatState) {
}
public void retrieveContactStatus(JID jid) {
}
public void resendContactStatuses(JID jid) {
}
public String getBareJID(String jid) {
return jid.substring(0, jid.indexOf("/"));
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.xmpp;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
/**
* XMPP Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class XMPPTransport extends BaseTransport {
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyUsername()
*/
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway."+getType().toString()+".username", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyPassword()
*/
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway.xmpp.password", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyNickname()
*/
public String getTerminologyNickname() {
return null;
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyRegistration()
*/
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway."+getType().toString()+".registration", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isPasswordRequired()
*/
public Boolean isPasswordRequired() { return true; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isNicknameRequired()
*/
public Boolean isNicknameRequired() { return false; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isUsernameValid(String)
*/
public Boolean isUsernameValid(String username) {
if (getType() == TransportType.icq) {
return username.matches("\\d+");
}
else {
return username.matches("\\w+") || username.matches("\\w+@[\\w\\.]+");
}
}
/**
* Handles creating an OSCAR session and triggering a login.
*
* @param registration Registration information to be used to log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new XMPPSession(registration, jid, this, priority);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
/**
* Handles logging out of a Yahoo session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.yahoo;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.Presence;
import org.openymsg.network.*;
import java.io.IOException;
import java.util.*;
/**
* Represents a Yahoo session.
*
* This is the interface with which the base transport functionality will
* communicate with Yahoo.
*
* @author Daniel Henninger
* Heavily inspired by Noah Campbell's work.
*/
public class YahooSession extends TransportSession {
final private PseudoRosterManager pseudoRosterManager = new PseudoRosterManager();
/**
* Create a Yahoo Session instance.
*
* @param registration Registration informationed used for logging in.
* @param jid JID associated with this session.
* @param transport Transport instance associated with this session
* @param priority Priority of this session
*/
public YahooSession(Registration registration, JID jid, YahooTransport transport, Integer priority) {
super(registration, jid, transport, priority);
pseudoRoster = pseudoRosterManager.getPseudoRoster(registration);
yahooSession = new Session(new DirectConnectionHandler(
JiveGlobals.getProperty("plugin.gateway.yahoo.connecthost", "scs.msg.yahoo.com"),
JiveGlobals.getIntProperty("plugin.gateway.yahoo.connectport", 5050)
));
yahooSession.addSessionListener(new YahooSessionListener(this));
}
/**
* Our pseudo roster.
*
* We only really use it for nickname tracking.
*/
private PseudoRoster pseudoRoster;
/**
* Yahoo session
*/
private final Session yahooSession;
/**
* Stored Last Presence Type
*/
public PresenceType presenceType = null;
/**
* Stored Last Verbose Status
*/
public String verboseStatus = null;
/**
* Log in to Yahoo.
*
* @param presenceType Type of presence.
* @param verboseStatus Long representation of status.
*/
public void logIn(PresenceType presenceType, String verboseStatus) {
this.presenceType = presenceType;
this.verboseStatus = verboseStatus;
final PresenceType pType = presenceType;
if (!isLoggedIn()) {
new Thread() {
public void run() {
try {
yahooSession.setStatus(Status.AVAILABLE);
yahooSession.login(registration.getUsername(), registration.getPassword());
setLoginStatus(TransportLoginStatus.LOGGED_IN);
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
yahooSession.setStatus(((YahooTransport)getTransport()).convertJabStatusToYahoo(pType));
getRegistration().setLastLogin(new Date());
syncUsers();
}
catch (LoginRefusedException e) {
yahooSession.reset();
String reason = LocaleUtils.getLocalizedString("gateway.yahoo.loginrefused", "gateway");
AuthenticationState state = e.getStatus();
if (state.equals(AuthenticationState.BADUSERNAME)) {
reason = LocaleUtils.getLocalizedString("gateway.yahoo.unknownuser", "gateway");
}
else if (state.equals(AuthenticationState.BAD)) {
reason = LocaleUtils.getLocalizedString("gateway.yahoo.badpassword", "gateway");
}
else if (state.equals(AuthenticationState.LOCKED)) {
AccountLockedException e2 = (AccountLockedException)e;
if(e2.getWebPage() != null) {
reason = LocaleUtils.getLocalizedString("gateway.yahoo.accountlockedwithurl", "gateway", Arrays.asList(e2.getWebPage().toString()));
}
else {
reason = LocaleUtils.getLocalizedString("gateway.yahoo.accountlocked", "gateway");
}
}
Log.warn("Yahoo login failed for "+getJID()+": "+reason);
getTransport().sendMessage(
getJID(),
getTransport().getJID(),
reason,
Message.Type.error
);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
catch (IOException e) {
Log.error("Yahoo login caused IO exception:", e);
getTransport().sendMessage(
getJID(),
getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.yahoo.unknownerror", "gateway"),
Message.Type.error
);
setLoginStatus(TransportLoginStatus.LOGGED_OUT);
}
}
}.start();
}
}
/**
* Log out of Yahoo.
*/
public void logOut() {
cleanUp();
sessionDisconnectedNoReconnect();
}
public void cleanUp() {
try {
yahooSession.logout();
}
catch (IOException e) {
Log.debug("Failed to log out from Yahoo.");
}
yahooSession.reset();
}
/**
* Syncs up the yahoo roster with the jabber roster.
*/
public void syncUsers() {
// First we need to get a good mapping of users to what groups they are in.
HashMap<String,ArrayList<String>> userToGroups = new HashMap<String,ArrayList<String>>();
for (YahooGroup group : yahooSession.getGroups()) {
for (YahooUser user : group.getMembers()) {
ArrayList<String> groups;
if (userToGroups.containsKey(user.getId())) {
groups = userToGroups.get(user.getId());
}
else {
groups = new ArrayList<String>();
}
if (!groups.contains(group.getName())) {
groups.add(group.getName());
}
userToGroups.put(user.getId(), groups);
}
}
// Now we will run through the entire list of users and set up our sync group.
List<TransportBuddy> legacyusers = new ArrayList<TransportBuddy>();
for (Object userObj : yahooSession.getUsers().values()) {
YahooUser user = (YahooUser)userObj;
PseudoRosterItem rosterItem = pseudoRoster.getItem(user.getId());
String nickname = null;
if (rosterItem != null) {
nickname = rosterItem.getNickname();
}
if (nickname == null) {
nickname = user.getId();
}
if (userToGroups.containsKey(user.getId()) && !userToGroups.get(user.getId()).get(0).equals("Transport Buddies")) {
legacyusers.add(new TransportBuddy(user.getId(), nickname, userToGroups.get(user.getId()).get(0)));
}
else {
legacyusers.add(new TransportBuddy(user.getId(), nickname, null));
}
}
// Lets try the actual sync.
try {
getTransport().syncLegacyRoster(getJID(), legacyusers);
}
catch (UserNotFoundException e) {
Log.error("Unable to sync yahoo contact list for " + getJID());
}
// Ok, now lets check presence
for (Object userObj : yahooSession.getUsers().values()) {
YahooUser user = (YahooUser)userObj;
Presence p = new Presence();
p.setTo(getJID());
p.setFrom(getTransport().convertIDToJID(user.getId()));
String custommsg = user.getCustomStatusMessage();
if (custommsg != null) {
p.setStatus(custommsg);
}
((YahooTransport)getTransport()).setUpPresencePacket(p, user.getStatus());
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#addContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void addContact(RosterItem item) {
// Syncing will take are of add.
String contact = getTransport().convertJIDToID(item.getJid());
lockRoster(item.getJid().toString());
syncContactGroups(contact, item.getGroups());
if (pseudoRoster.hasItem(contact)) {
PseudoRosterItem rosterItem = pseudoRoster.getItem(contact);
rosterItem.setNickname(item.getNickname());
}
else {
pseudoRoster.createItem(contact, item.getNickname(), null);
}
unlockRoster(item.getJid().toString());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#removeContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void removeContact(RosterItem item) {
String contact = getTransport().convertJIDToID(item.getJid());
YahooUser yUser = new YahooUser(contact);
lockRoster(item.getJid().toString());
for (YahooGroup yahooGroup : yahooSession.getGroups()) {
if (yahooGroup.contains(yUser)) {
try {
yahooSession.removeFriend(contact, yahooGroup.getName());
pseudoRoster.removeItem(contact);
}
catch (IOException e) {
Log.error("Failed to remove yahoo user.");
}
}
}
unlockRoster(item.getJid().toString());
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateContact(org.jivesoftware.openfire.roster.RosterItem)
*/
public void updateContact(RosterItem item) {
String contact = getTransport().convertJIDToID(item.getJid());
lockRoster(item.getJid().toString());
syncContactGroups(contact, item.getGroups());
if (pseudoRoster.hasItem(contact)) {
PseudoRosterItem rosterItem = pseudoRoster.getItem(contact);
rosterItem.setNickname(item.getNickname());
}
else {
pseudoRoster.createItem(contact, item.getNickname(), null);
}
unlockRoster(item.getJid().toString());
}
/**
* Given a legacy contact and a list of groups, makes sure that the list is in sync with
* the actual group list.
*
* @param contact Email address of contact.
* @param groups List of groups contact should be in.
*/
public void syncContactGroups(String contact, List<String> groups) {
YahooUser yUser = new YahooUser(contact);
if (groups.size() == 0) {
groups.add("Transport Buddies");
}
HashMap<String,YahooGroup> yahooGroups = new HashMap<String,YahooGroup>();
// Lets create a hash of these for easier reference.
for (YahooGroup yahooGroup : yahooSession.getGroups()) {
yahooGroups.put(yahooGroup.getName(), yahooGroup);
}
// Create groups(add user to them) that do not currently exist.
for (String group : groups) {
if (!yahooGroups.containsKey(group)) {
try {
Log.debug("Yahoo: Adding contact "+contact+" to non-existent group "+group);
yahooSession.addFriend(contact, group);
}
catch (IOException e) {
Log.error("Error while syncing Yahoo groups.");
}
}
}
// Now we handle adds and removes, syncing the two lists.
for (YahooGroup yahooGroup : yahooSession.getGroups()) {
if (groups.contains(yahooGroup.getName())) {
if (yahooGroup.contains(yUser)) {
try {
Log.debug("Yahoo: Adding contact "+contact+" to existing group "+yahooGroup.getName());
yahooSession.addFriend(contact, yahooGroup.getName());
}
catch (IOException e) {
Log.error("Error while syncing Yahoo groups.");
}
}
}
else {
if (yahooGroup.contains(yUser)) {
try {
Log.debug("Yahoo: Removing contact "+contact+" from group "+yahooGroup.getName());
yahooSession.removeFriend(contact, yahooGroup.getName());
}
catch (IOException e) {
Log.error("Error while syncing Yahoo groups.");
}
}
}
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendMessage(org.xmpp.packet.JID, String)
*/
public void sendMessage(JID jid, String message) {
try {
yahooSession.sendMessage(jid.getNode(), message);
}
catch (IOException e) {
Log.error("Failed to send message to yahoo user.");
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendServerMessage(String)
*/
public void sendServerMessage(String message) {
// We don't care.
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#sendChatState(org.xmpp.packet.JID, org.jivesoftware.openfire.gateway.ChatStateType)
*/
public void sendChatState(JID jid, ChatStateType chatState) {
// TODO: Handle this
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#updateStatus(org.jivesoftware.openfire.gateway.PresenceType, String)
*/
public void updateStatus(PresenceType presenceType, String verboseStatus) {
try {
if (isLoggedIn()) {
yahooSession.setStatus(((YahooTransport)getTransport()).convertJabStatusToYahoo(presenceType));
}
else {
// TODO: Should we consider auto-logging back in?
}
}
catch (Exception e) {
Log.error("Unable to set Yahoo Status:", e);
}
Presence p = new Presence();
if (presenceType == PresenceType.away) {
p.setShow(Presence.Show.away);
}
else if (presenceType == PresenceType.xa) {
p.setShow(Presence.Show.xa);
}
else if (presenceType == PresenceType.dnd) {
p.setShow(Presence.Show.dnd);
}
else if (presenceType == PresenceType.chat) {
p.setShow(Presence.Show.chat);
}
p.setTo(getJID());
p.setFrom(getTransport().getJID());
getTransport().sendPacket(p);
this.presenceType = presenceType;
this.verboseStatus = verboseStatus;
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#retrieveContactStatus(org.xmpp.packet.JID)
*/
public void retrieveContactStatus(JID jid) {
if (isLoggedIn()) {
YahooUser user = yahooSession.getUser(jid.getNode());
Presence p = new Presence();
p.setTo(getJID());
if (user != null) {
// User was found so update presence accordingly
p.setFrom(getTransport().convertIDToJID(user.getId()));
String custommsg = user.getCustomStatusMessage();
if (custommsg != null) {
p.setStatus(custommsg);
}
((YahooTransport)getTransport()).setUpPresencePacket(p, user.getStatus());
}
else {
// User was not found so send an error presence
p.setFrom(jid);
p.setError(PacketError.Condition.forbidden);
}
getTransport().sendPacket(p);
}
}
/**
* @see org.jivesoftware.openfire.gateway.TransportSession#resendContactStatuses(org.xmpp.packet.JID)
*/
public void resendContactStatuses(JID jid) {
for (Object userObj : yahooSession.getUsers().values()) {
YahooUser user = (YahooUser)userObj;
Presence p = new Presence();
p.setTo(jid);
p.setFrom(getTransport().convertIDToJID(user.getId()));
String custommsg = user.getCustomStatusMessage();
if (custommsg != null) {
p.setStatus(custommsg);
}
((YahooTransport)getTransport()).setUpPresencePacket(p, user.getStatus());
getTransport().sendPacket(p);
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.yahoo;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.TransportLoginStatus;
import org.xmpp.packet.Message;
import org.xmpp.packet.Presence;
import org.openymsg.network.YahooUser;
import org.openymsg.network.StatusConstants;
import org.openymsg.network.event.*;
import org.openymsg.support.MessageDecoder;
import java.util.Arrays;
/**
* Handles incoming packets from Yahoo.
*
* This takes care of events we don't do anything with yet by logging them.
*
* @author Daniel Henninger
* Heavily inspired by Noah Campbell's work.
*/
public class YahooSessionListener implements SessionListener {
/**
* Handles converting messages between formats.
*/
private MessageDecoder messageDecoder = new MessageDecoder();
/**
* Creates a Yahoo session listener affiliated with a session.
*
* @param session The YahooSession instance we are associatd with.
*/
public YahooSessionListener(YahooSession session) {
this.yahooSession = session;
}
/**
* The transport session we are affiliated with.
*/
YahooSession yahooSession;
/**
* @see org.openymsg.network.event.SessionListener#messageReceived(org.openymsg.network.event.SessionEvent)
*/
public void messageReceived(SessionEvent event) {
yahooSession.getTransport().sendMessage(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().convertIDToJID(event.getFrom()),
messageDecoder.decodeToText(event.getMessage())
);
}
/**
* @see org.openymsg.network.event.SessionListener#offlineMessageReceived(org.openymsg.network.event.SessionEvent)
*/
public void offlineMessageReceived(SessionEvent event) {
yahooSession.getTransport().sendMessage(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().convertIDToJID(event.getFrom()),
messageDecoder.decodeToText(event.getMessage())
);
}
/**
* @see org.openymsg.network.event.SessionListener#newMailReceived(org.openymsg.network.event.SessionNewMailEvent)
*/
public void newMailReceived(SessionNewMailEvent event) {
if (event.getMailCount() > 0) {
yahooSession.getTransport().sendMessage(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.yahoo.mail", "gateway", Arrays.asList(Integer.toString(event.getMailCount()))),
Message.Type.headline
);
}
}
/**
* @see org.openymsg.network.event.SessionListener#friendsUpdateReceived(org.openymsg.network.event.SessionFriendEvent)
*/
public void friendsUpdateReceived(SessionFriendEvent event) {
for (YahooUser user : event.getFriends()) {
Presence p = new Presence();
p.setTo(yahooSession.getJID());
p.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
String custommsg = user.getCustomStatusMessage();
if (custommsg != null) {
p.setStatus(custommsg);
}
((YahooTransport)yahooSession.getTransport()).setUpPresencePacket(p, user.getStatus());
yahooSession.getTransport().sendPacket(p);
}
}
/**
* @see org.openymsg.network.event.SessionListener#friendAddedReceived(org.openymsg.network.event.SessionFriendEvent)
*/
public void friendAddedReceived(SessionFriendEvent event) {
Presence p = new Presence(Presence.Type.subscribe);
p.setTo(yahooSession.getJID());
p.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
yahooSession.getTransport().sendPacket(p);
}
/**
* @see org.openymsg.network.event.SessionListener#friendRemovedReceived(org.openymsg.network.event.SessionFriendEvent)
*/
public void friendRemovedReceived(SessionFriendEvent event) {
Presence p = new Presence(Presence.Type.unsubscribe);
p.setTo(yahooSession.getJID());
p.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
yahooSession.getTransport().sendPacket(p);
}
/**
* @see org.openymsg.network.event.SessionListener#groupRenameReceived(org.openymsg.network.event.SessionGroupEvent)
*/
public void groupRenameReceived(SessionGroupEvent sessionGroupEvent) {
// TODO: Handle this
}
/**
* @see org.openymsg.network.event.SessionListener#chatJoinReceived(org.openymsg.network.event.SessionChatEvent)
*/
public void chatJoinReceived(SessionChatEvent sessionChatEvent) {
}
/**
* @see org.openymsg.network.event.SessionListener#chatExitReceived(org.openymsg.network.event.SessionChatEvent)
*/
public void chatExitReceived(SessionChatEvent sessionChatEvent) {
}
/**
* @see org.openymsg.network.event.SessionListener#connectionClosed(org.openymsg.network.event.SessionEvent)
*/
public void connectionClosed(SessionEvent event) {
Log.debug(event.toString());
if (yahooSession.isLoggedIn()) {
yahooSession.setLoginStatus(TransportLoginStatus.DISCONNECTED);
yahooSession.sessionDisconnectedNoReconnect();
}
}
/**
* @see org.openymsg.network.event.SessionListener#fileTransferReceived(org.openymsg.network.event.SessionFileTransferEvent)
*/
public void fileTransferReceived(SessionFileTransferEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#listReceived(org.openymsg.network.event.SessionEvent)
*/
public void listReceived(SessionEvent event) {
// We just got the entire contact list. Lets sync up.
yahooSession.syncUsers();
}
/**
* @see org.openymsg.network.event.SessionListener#buzzReceived(org.openymsg.network.event.SessionEvent)
*/
public void buzzReceived(SessionEvent event) {
yahooSession.getTransport().sendMessage(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().convertIDToJID(event.getFrom()),
messageDecoder.decodeToText(event.getMessage())
);
}
/**
* @see org.openymsg.network.event.SessionListener#errorPacketReceived(org.openymsg.network.event.SessionErrorEvent)
*/
public void errorPacketReceived(SessionErrorEvent event) {
Log.error("Error from yahoo: "+event.getMessage()+", Code:"+event.getCode());
yahooSession.getTransport().sendMessage(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().getJID(),
LocaleUtils.getLocalizedString("gateway.yahoo.error", "gateway")+" "+event.getMessage(),
Message.Type.error
);
}
/**
* @see org.openymsg.network.event.SessionListener#inputExceptionThrown(org.openymsg.network.event.SessionExceptionEvent)
*/
public void inputExceptionThrown(SessionExceptionEvent event) {
Log.error("Input error from yahoo: "+event.getMessage(), event.getException());
// Lets keep this silent for now. Not bother the end user with it.
// yahooSession.getTransport().sendMessage(
// yahooSession.getJIDWithHighestPriority(),
// yahooSession.getTransport().getJID(),
// "Input error from yahoo: "+event.getMessage(),
// Message.Type.error
// );
}
/**
* @see org.openymsg.network.event.SessionListener#notifyReceived(org.openymsg.network.event.SessionNotifyEvent)
*/
public void notifyReceived(SessionNotifyEvent event) {
Log.debug(event.toString());
if (event.getType().equals(StatusConstants.NOTIFY_TYPING)) {
yahooSession.getTransport().sendComposingNotification(
yahooSession.getJIDWithHighestPriority(),
yahooSession.getTransport().convertIDToJID(event.getFrom())
);
}
}
/**
* @see org.openymsg.network.event.SessionListener#contactRequestReceived(org.openymsg.network.event.SessionEvent)
*/
public void contactRequestReceived(SessionEvent event) {
Presence p = new Presence(Presence.Type.subscribe);
p.setTo(yahooSession.getJID());
p.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
yahooSession.getTransport().sendPacket(p);
}
/**
* @see org.openymsg.network.event.SessionListener#contactRejectionReceived(org.openymsg.network.event.SessionEvent)
*/
public void contactRejectionReceived(SessionEvent event) {
// TODO: Is this correct? unsubscribed for a rejection?
Log.debug(event.toString());
Presence p = new Presence(Presence.Type.unsubscribed);
p.setTo(yahooSession.getJID());
p.setFrom(yahooSession.getTransport().convertIDToJID(event.getFrom()));
yahooSession.getTransport().sendPacket(p);
}
/**
* @see org.openymsg.network.event.SessionListener#conferenceInviteReceived(org.openymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#conferenceInviteDeclinedReceived(org.openymsg.network.event.SessionConferenceEvent)
*/
public void conferenceInviteDeclinedReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#conferenceLogonReceived(org.openymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogonReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#conferenceLogoffReceived(org.openymsg.network.event.SessionConferenceEvent)
*/
public void conferenceLogoffReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#conferenceMessageReceived(org.openymsg.network.event.SessionConferenceEvent)
*/
public void conferenceMessageReceived(SessionConferenceEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#chatMessageReceived(org.openymsg.network.event.SessionChatEvent)
*/
public void chatMessageReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#chatUserUpdateReceived(org.openymsg.network.event.SessionChatEvent)
*/
public void chatUserUpdateReceived(SessionChatEvent event) {
Log.debug(event.toString());
}
/**
* @see org.openymsg.network.event.SessionListener#chatConnectionClosed(org.openymsg.network.event.SessionEvent)
*/
public void chatConnectionClosed(SessionEvent event) {
Log.debug(event.toString());
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.protocols.yahoo;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.openfire.gateway.*;
import org.xmpp.packet.JID;
import org.xmpp.packet.Presence;
import org.openymsg.network.Status;
/**
* Yahoo Transport Interface.
*
* This handles the bulk of the XMPP work via BaseTransport and provides
* some gateway specific interactions.
*
* @author Daniel Henninger
*/
public class YahooTransport extends BaseTransport {
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyUsername()
*/
public String getTerminologyUsername() {
return LocaleUtils.getLocalizedString("gateway.yahoo.username", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyPassword()
*/
public String getTerminologyPassword() {
return LocaleUtils.getLocalizedString("gateway.yahoo.password", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyNickname()
*/
public String getTerminologyNickname() {
return null;
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#getTerminologyRegistration()
*/
public String getTerminologyRegistration() {
return LocaleUtils.getLocalizedString("gateway.yahoo.registration", "gateway");
}
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isPasswordRequired()
*/
public Boolean isPasswordRequired() { return true; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isNicknameRequired()
*/
public Boolean isNicknameRequired() { return false; }
/**
* @see org.jivesoftware.openfire.gateway.BaseTransport#isUsernameValid(String)
*/
public Boolean isUsernameValid(String username) {
return username.matches("[^ \\p{Cntrl}()@,;:\\\\\"\\[\\]]+@?[^ \\p{Cntrl}()@,;:\\\\\"\\[\\]]+");
}
/**
* Handles creating a Yahoo session and triggering a login.
*
* @param registration Registration information to be used to log in.
* @param jid JID that is logged into the transport.
* @param presenceType Type of presence.
* @param verboseStatus Longer status description.
*/
public TransportSession registrationLoggedIn(Registration registration, JID jid, PresenceType presenceType, String verboseStatus, Integer priority) {
TransportSession session = new YahooSession(registration, jid, this, priority);
session.setLoginStatus(TransportLoginStatus.LOGGING_IN);
session.logIn(presenceType, verboseStatus);
return session;
}
/**
* Handles logging out of a Yahoo session.
*
* @param session The session to be disconnected.
*/
public void registrationLoggedOut(TransportSession session) {
session.setLoginStatus(TransportLoginStatus.LOGGING_OUT);
session.logOut();
}
/**
* Converts a jabber status to an Yahoo status.
*
* @param jabStatus Jabber presence type.
* @return Yahoo status identifier.
*/
public Status convertJabStatusToYahoo(PresenceType jabStatus) {
if (jabStatus == PresenceType.available) {
return Status.AVAILABLE;
}
else if (jabStatus == PresenceType.away) {
return Status.BRB;
}
else if (jabStatus == PresenceType.xa) {
return Status.STEPPEDOUT;
}
else if (jabStatus == PresenceType.dnd) {
return Status.BUSY;
}
else if (jabStatus == PresenceType.chat) {
return Status.AVAILABLE;
}
else if (jabStatus == PresenceType.unavailable) {
return Status.OFFLINE;
}
else {
return Status.AVAILABLE;
}
}
/**
* Sets up a presence packet according to Yahoo status.
*
* @param packet Presence packet to be set up.
* @param yahooStatus Yahoo StatusConstants constant.
*/
public void setUpPresencePacket(Presence packet, Status yahooStatus) {
if (yahooStatus == Status.AVAILABLE) {
// We're good, leave the type as blank for available.
}
else if (yahooStatus == Status.BRB) {
packet.setShow(Presence.Show.away);
}
else if (yahooStatus == Status.BUSY) {
packet.setShow(Presence.Show.dnd);
}
else if (yahooStatus == Status.IDLE) {
packet.setShow(Presence.Show.away);
}
else if (yahooStatus == Status.OFFLINE) {
packet.setType(Presence.Type.unavailable);
}
else if (yahooStatus == Status.NOTATDESK) {
packet.setShow(Presence.Show.away);
}
else if (yahooStatus == Status.NOTINOFFICE) {
packet.setShow(Presence.Show.away);
}
else if (yahooStatus == Status.ONPHONE) {
packet.setShow(Presence.Show.away);
}
else if (yahooStatus == Status.ONVACATION) {
packet.setShow(Presence.Show.xa);
}
else if (yahooStatus == Status.OUTTOLUNCH) {
packet.setShow(Presence.Show.xa);
}
else if (yahooStatus == Status.STEPPEDOUT) {
packet.setShow(Presence.Show.away);
}
else {
// Not something we handle, we're going to ignore it.
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.web;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.user.UserManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.gateway.GatewayPlugin;
import org.jivesoftware.openfire.gateway.TransportType;
import org.jivesoftware.openfire.gateway.PermissionManager;
import org.jivesoftware.openfire.gateway.Registration;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.util.LocaleUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Attribute;
import org.xmpp.packet.JID;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
/**
* Transport Configuration Manager (for web interface)
*
* Handles web interface interactions with the transport instances, such as enabling or
* disabling them, configuring options, etc.
*
* @author Daniel Henninger
*/
public class ConfigManager {
/**
* Toggles whether a transport is enabled or disabled.
*
* @param transportName Name of the transport to be enabled or disabled (type of transport)
* @return True or false if the transport is enabled after this call.
*/
public boolean toggleTransport(String transportName) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
GatewayPlugin plugin = (GatewayPlugin)pluginManager.getPlugin("gateway");
if (!plugin.serviceEnabled(transportName)) {
plugin.enableService(transportName);
return true;
}
else {
plugin.disableService(transportName);
return false;
}
}
/**
* Saves settings from options screen.
*
* @param transportName Name of the transport to have it's options saved (type of transport)
* @param options Options passed from options form.
*/
public void saveSettings(String transportName, HashMap<String,String> options) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
GatewayPlugin plugin = (GatewayPlugin)pluginManager.getPlugin("gateway");
Document optConfig = plugin.getOptionsConfig(TransportType.valueOf(transportName));
Element leftPanel = optConfig.getRootElement().element("leftpanel");
if (leftPanel != null && leftPanel.nodeCount() > 0) {
for (Object nodeObj : leftPanel.elements("item")) {
Element node = (Element)nodeObj;
saveOptionSetting(node, options);
}
}
Element rightPanel = optConfig.getRootElement().element("rightpanel");
if (rightPanel != null && rightPanel.nodeCount() > 0) {
for (Object nodeObj : rightPanel.elements("item")) {
Element node = (Element)nodeObj;
saveOptionSetting(node, options);
}
}
}
/**
* Helper function designed to handle saving option types.
*
* @param node Node describing the configuration item.
* @param options Options passed from form.
*/
private void saveOptionSetting(Element node, HashMap<String,String> options) {
Attribute type = node.attribute("type");
if (type.getText().equals("text")) {
// Required fields
Attribute desckey = node.attribute("desckey");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
if (desckey == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
return;
}
// Process any variables that we are setting.
if (var.getText().equals("host")) {
JiveGlobals.setProperty(sysprop.getText(), options.get("host"));
}
else if (var.getText().equals("port")) {
JiveGlobals.setProperty(sysprop.getText(), options.get("port"));
}
else if (var.getText().equals("encoding")) {
JiveGlobals.setProperty(sysprop.getText(), options.get("encoding"));
}
}
else if (type.getText().equals("toggle")) {
// Required fields
Attribute desckey = node.attribute("desckey");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
if (desckey == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
return;
}
// Process any variables that we are setting.
// None yet.
for (Object itemObj : node.elements("item")) {
Element item = (Element)itemObj;
saveOptionSetting(item, options);
}
}
}
/**
* Saves permissions settings from web interface.
*
* We validate all of the groups before actually adding them.
*
* @param transportName Name of the transport to have it's options saved (type of transport)
* @param overallSetting The general "all(1), some(2), or none(3)" setting for the permissions.
* @param users List of specific users that have access.
* @param groups List of specific groups that have access.
* @return List of usernames and groups (@ preceded) that were rejected.
*/
public List<String> savePermissions(String transportName, Integer overallSetting, List<String> users, List<String> groups) {
JiveGlobals.setProperty("plugin.gateway."+transportName+".registration", overallSetting.toString());
PermissionManager permissionManager = new PermissionManager(TransportType.valueOf(transportName));
List<String> errorList = new ArrayList<String>();
ArrayList<User> userList = new ArrayList<User>();
UserManager userManager = UserManager.getInstance();
for (String username : users) {
if (username.matches("\\s*")) { continue; }
try {
if (username.contains("@")) {
JID jid = new JID(username);
if (!jid.getDomain().equals(XMPPServer.getInstance().getServerInfo().getName())) {
throw new UserNotFoundException();
}
username = username.substring(0, username.indexOf("@"));
}
User user = userManager.getUser(username);
if (user == null || user.getUsername() == null) { throw new UserNotFoundException(); }
userList.add(user);
}
catch (UserNotFoundException e) {
Log.warn("User "+username+" not found while adding access rules.");
errorList.add(username);
}
}
permissionManager.storeUserList(userList);
ArrayList<Group> groupList = new ArrayList<Group>();
GroupManager groupManager = GroupManager.getInstance();
for (String grpname : groups) {
if (grpname.matches("\\s*")) { continue; }
try {
Group group = groupManager.getGroup(grpname);
if (group == null || group.getName() == null) { throw new GroupNotFoundException(); }
groupList.add(group);
}
catch (GroupNotFoundException e) {
Log.warn("Group "+grpname+" not found while adding access rules.");
errorList.add("@"+grpname);
}
}
permissionManager.storeGroupList(groupList);
return errorList;
}
/**
* Adds a new registration via the web interface.
*
* @param user Username or full JID of user who is getting an account registered.
* @param transportType Type of transport to add user to.
* @param legacyUsername User's username on the legacy service.
* @param legacyPassword User's password on the legacy service.
* @param legacyNickname User's nickname on the legacy service.
* @return Error message or null on success.
*/
public String addRegistration(String user, String transportType, String legacyUsername, String legacyPassword, String legacyNickname) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
GatewayPlugin plugin = (GatewayPlugin)pluginManager.getPlugin("gateway");
JID jid;
if (user.contains("@")) {
jid = new JID(user);
}
else {
jid = new JID(user, XMPPServer.getInstance().getServerInfo().getName(), null);
}
if (!plugin.getTransportInstance(transportType).isEnabled()) {
return LocaleUtils.getLocalizedString("gateway.web.registrations.notenabled", "gateway");
}
try {
plugin.getTransportInstance(transportType).getTransport().addNewRegistration(jid, legacyUsername, legacyPassword, legacyNickname, false);
return null;
}
catch (UserNotFoundException e) {
Log.error("Not found while adding account for "+jid.toString());
return LocaleUtils.getLocalizedString("gateway.web.registrations.xmppnotfound", "gateway");
}
catch (IllegalAccessException e) {
Log.error("Domain of JID specified for registration is not on this server: "+jid.toString());
return LocaleUtils.getLocalizedString("gateway.web.registrations.illegaldomain", "gateway");
}
catch (IllegalArgumentException e) {
Log.error("Username specified for registration is not valid.");
return LocaleUtils.getLocalizedString("gateway.web.registrations.invaliduser", "gateway");
}
}
/**
* Deletes a registration via the web interface.
*
* @param registrationID ID number associated with registration to delete.
* @return Error message or null on success.
*/
public String deleteRegistration(Integer registrationID) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
GatewayPlugin plugin = (GatewayPlugin)pluginManager.getPlugin("gateway");
try {
Registration reg = new Registration(registrationID);
if (!plugin.getTransportInstance(reg.getTransportType().toString()).isEnabled()) {
return LocaleUtils.getLocalizedString("gateway.web.registrations.notenabled", "gateway");
}
plugin.getTransportInstance(reg.getTransportType().toString()).getTransport().deleteRegistration(reg.getJID());
return null;
}
catch (NotFoundException e) {
// Ok, nevermind.
Log.error("Not found while deleting id "+registrationID, e);
return LocaleUtils.getLocalizedString("gateway.web.registrations.xmppnotfound", "gateway");
}
catch (UserNotFoundException e) {
// Ok, nevermind.
Log.error("Not found while deleting id "+registrationID, e);
return LocaleUtils.getLocalizedString("gateway.web.registrations.regnotfound", "gateway");
}
}
/**
* Updates a registration via the web interface.
*
*
* @param registrationID ID number associated with registration to modify.
* @param legacyUsername User's updated username on the legacy service.
* @param legacyPassword User's updated password on the legacy service, null if no change.
* @param legacyNickname User's updated nickname on the legacy service.
* @return Error message or null on success.
*/
public String updateRegistration(Integer registrationID, String legacyUsername, String legacyPassword, String legacyNickname) {
PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();
GatewayPlugin plugin = (GatewayPlugin)pluginManager.getPlugin("gateway");
try {
Registration reg = new Registration(registrationID);
if (!plugin.getTransportInstance(reg.getTransportType().toString()).isEnabled()) {
return LocaleUtils.getLocalizedString("gateway.web.registrations.notenabled", "gateway");
}
reg.setUsername(legacyUsername);
if (legacyPassword != null) {
reg.setPassword(legacyPassword);
}
reg.setNickname(legacyNickname);
return null;
}
catch (NotFoundException e) {
// Ok, nevermind.
Log.error("Not found while editing id "+registrationID, e);
return LocaleUtils.getLocalizedString("gateway.web.registrations.regnotfound", "gateway");
}
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.web;
import java.net.Socket;
/**
* Connection Tester
*
* This class tests a connection with a legacy service (just simple open port tcp check).
*
* @author Daniel Henninger
*/
public class ConnectionTester {
/**
* Tests a tcp connection to a host and port.
*
* @param host Hostname (or ip address) to try to connect to.
* @param port Port to try to connect to.
* @return True or false if the connection succeeded.
*/
public boolean testConnection(String host, String port) {
try {
Socket sock = new Socket(host, Integer.parseInt(port));
sock.close();
return true;
}
catch (Exception e) {
return false;
}
}
/**
* Cheesy DWR 'ping' to make sure session stays alive.
* Literally does nothing.
*/
public void pingSession() {
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.web;
import org.apache.axis.transport.http.AxisServlet;
import org.apache.axis.configuration.XMLStringProvider;
import org.apache.axis.AxisEngine;
import org.apache.axis.EngineConfiguration;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import org.jivesoftware.util.Log;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import java.util.HashMap;
import java.util.Map;
/**
* @author Daniel Henninger
*/
public class GatewayAxis extends AxisServlet {
private static Document document;
/*public void init() throws javax.servlet.ServletException {
webInfPath = "../../gateway/WEB-INF";
homeDir = "../../gateway/";
System.out.println("webInfPath = "+webInfPath);
System.out.println("homeDir = "+homeDir);
}*/
protected static Map getEngineEnvironment(HttpServlet servlet) {
Map environment = new HashMap();
System.out.println("'sup yo");
ServletContext context = servlet.getServletContext();
environment.put(AxisEngine.ENV_SERVLET_CONTEXT, context);
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
document = builder.newDocument();
Element root = document.createElement("service");
root.setAttribute("name", "ConnectionTester");
root.setAttribute("provider", "java:RPC");
Element parameter = document.createElement("parameter");
parameter.setAttribute("name", "allowedMethods");
parameter.setAttribute("value", "*");
root.appendChild(parameter);
parameter = document.createElement("parameter");
parameter.setAttribute("name", "className");
parameter.setAttribute("value", "org.jivesoftware.openfire.gateway.web.ConnectionTester");
root.appendChild(parameter);
document.appendChild(root);
EngineConfiguration config = new XMLStringProvider(document.toString());
environment.put(EngineConfiguration.PROPERTY_NAME, config);
}
catch (ParserConfigurationException e) {
Log.error("Error configuring Axis for gateway plugin: ", e);
}
return environment;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.gateway.web;
import uk.ltd.getahead.dwr.DWRServlet;
import uk.ltd.getahead.dwr.Configuration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.jivesoftware.util.Log;
/**
* IM Gateway DWR servlet
*
* Handles DWR configuration/etc for AJAX interaction.
*
* @author Daniel Henninger
*/
public class GatewayDWR extends DWRServlet {
private Document document;
public void configure(ServletConfig servletConfig, Configuration configuration) throws ServletException {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
document = builder.newDocument();
Element root = document.createElement("dwr");
document.appendChild(root);
Element allowElement = document.createElement("allow");
allowElement.appendChild(buildCreator("ConfigManager", "org.jivesoftware.openfire.gateway.web.ConfigManager"));
allowElement.appendChild(buildCreator("ConnectionTester", "org.jivesoftware.openfire.gateway.web.ConnectionTester"));
root.appendChild(allowElement);
}
catch (ParserConfigurationException e) {
Log.error("Error configuring DWR for gateway plugin: ", e);
}
configuration.addConfig(document);
}
/**
* Builds a create element within the DWR servlet.
* @param javascriptID the javascript variable name to use.
* @param qualifiedClassName the fully qualified class name.
* @return the Element.
*/
private Element buildCreator(String javascriptID, String qualifiedClassName) {
Element element = document.createElement("create");
element.setAttribute("creator", "new");
element.setAttribute("javascript", javascriptID);
Element parameter = document.createElement("param");
parameter.setAttribute("name", "class");
parameter.setAttribute("value", qualifiedClassName);
element.appendChild(parameter);
return element;
}
}
/**
* $Revision$
* $Date$
*
* Copyright (C) 2006-2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.util;
import org.jivesoftware.openfire.gateway.PresenceType;
import org.jivesoftware.openfire.gateway.Registration;
import org.jivesoftware.openfire.gateway.TransportSession;
import org.jivesoftware.openfire.gateway.TransportType;
import org.xmpp.packet.JID;
import org.jivesoftware.openfire.gateway.protocols.msn.MSNTransport;
public class MSNTransportTest
{
/**
* @param args Arguments passed to program.
*/
public static void main(String[] args)
{
if (args.length!=4)
{
System.out.println("Syntax: java MSNTransportTest user password nickname jid");
System.exit(0);
}
Log.setDebugEnabled(true);
JID jid = new JID(args[3]);
Registration registration = new Registration(jid, TransportType.msn, args[0], args[1], args[2], true);
MSNTransport transport = new MSNTransport();
transport.jid = jid;
transport.setup(TransportType.msn, "MSN");
TransportSession session = transport.registrationLoggedIn(registration,jid,PresenceType.available,"online",new Integer(1));
transport.registrationLoggedOut(session);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.aim.connecthost" var="host" desckey="gateway.web.settings.host" default="login.oscar.aol.com"/>
<item type="text" sysprop="plugin.gateway.aim.connectport" var="port" desckey="gateway.web.settings.port" default="5190"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.gtalk.connecthost" var="host" desckey="gateway.web.settings.host" default="talk.google.com"/>
<item type="text" sysprop="plugin.gateway.gtalk.connectport" var="port" desckey="gateway.web.settings.port" default="5222"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.icq.connecthost" var="host" desckey="gateway.web.settings.host" default="login.oscar.aol.com"/>
<item type="text" sysprop="plugin.gateway.icq.connectport" var="port" desckey="gateway.web.settings.port" default="5190"/>
<item type="text" sysprop="plugin.gateway.icq.encoding" var="encoding" desckey="gateway.web.settings.encoding" default="iso-8859-1"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.irc.connecthost" var="host" desckey="gateway.web.settings.host" default="irc.freenode.net"/>
<item type="text" sysprop="plugin.gateway.irc.connectport" var="port" desckey="gateway.web.settings.port" default="7000"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.msn.connecthost" var="host" desckey="gateway.web.settings.host" default="messenger.hotmail.com"/>
<item type="text" sysprop="plugin.gateway.msn.connectport" var="port" desckey="gateway.web.settings.port" default="1863"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.xmpp.connecthost" var="host" desckey="gateway.web.settings.host" default="jabber.org"/>
<item type="text" sysprop="plugin.gateway.xmpp.connectport" var="port" desckey="gateway.web.settings.port" default="5222"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<optionsconfig>
<leftpanel></leftpanel>
<rightpanel>
<item type="text" sysprop="plugin.gateway.yahoo.connecthost" var="host" desckey="gateway.web.settings.host" default="scs.msg.yahoo.com"/>
<item type="text" sysprop="plugin.gateway.yahoo.connectport" var="port" desckey="gateway.web.settings.port" default="5050"/>
</rightpanel>
</optionsconfig>
\ No newline at end of file
<service name="ConnectionTester" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="org.jivesoftware.openfire.gateway.web.ConnectionTester"/>
</service>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Listeners -->
<!--<listener>
<listener-class>org.apache.axis.transport.http.AxisHTTPSessionListener</listener-class>
</listener>-->
<!-- Servlets -->
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<description>Direct Web Remoter Servlet</description>
<servlet-class>org.jivesoftware.openfire.gateway.web.GatewayDWR</servlet-class>
<init-param>
<param-name>LogLevel</param-name>
<param-value>FATAL</param-value>
</init-param>
<init-param>
<param-name>skipDefaultConfig</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<!--<servlet>
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>org.jivesoftware.openfire.gateway.web.GatewayAxis</servlet-class>
</servlet>-->
<!-- Servlet mappings -->
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<!--<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>*.jws</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>-->
<!-- Mime mappings -->
<!--<mime-mapping>
<extension>wsdl</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xsd</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>-->
</web-app>
<%@ page import="java.io.*,
org.jivesoftware.util.JiveGlobals,
org.jivesoftware.openfire.auth.UnauthorizedException"
isErrorPage="true"
%>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<% boolean debug = "true".equals(JiveGlobals.getProperty("skin.default.debug"));
if (debug) {
exception.printStackTrace();
}
%>
<% if (exception instanceof UnauthorizedException) { %>
<p>
<fmt:message key="error.admin_privileges" />
</p>
<% } %>
<% if (exception != null) {
StringWriter sout = new StringWriter();
PrintWriter pout = new PrintWriter(sout);
exception.printStackTrace(pout);
%>
<fmt:message key="error.exception" />
<pre>
<%= sout.toString() %>
</pre>
<% } %>
\ No newline at end of file
<%@ page import="org.jivesoftware.util.ParamUtils,
org.jivesoftware.util.LocaleUtils,
org.jivesoftware.openfire.SessionManager,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.gateway.GatewayPlugin,
org.jivesoftware.openfire.gateway.Registration,
org.jivesoftware.openfire.gateway.RegistrationManager,
org.jivesoftware.openfire.session.ClientSession,
org.xmpp.packet.JID"
errorPage="error.jsp"
%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="org.xmpp.packet.Presence" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Collection" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.util.HashMap" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager" />
<%
final GatewayPlugin plugin =
(GatewayPlugin)XMPPServer.getInstance().getPluginManager().getPlugin("gateway");
HashMap<String,Boolean> trEnabled = new HashMap<String,Boolean>();
trEnabled.put("aim", plugin.getTransportInstance("aim").isEnabled());
trEnabled.put("gtalk", plugin.getTransportInstance("gtalk").isEnabled());
trEnabled.put("icq", plugin.getTransportInstance("icq").isEnabled());
trEnabled.put("irc", plugin.getTransportInstance("irc").isEnabled());
trEnabled.put("msn", plugin.getTransportInstance("msn").isEnabled());
trEnabled.put("xmpp", plugin.getTransportInstance("xmpp").isEnabled());
trEnabled.put("yahoo", plugin.getTransportInstance("yahoo").isEnabled());
webManager.init(request, response, session, application, out);
RegistrationManager registrationManager = new RegistrationManager();
Collection<Registration> registrations = registrationManager.getRegistrations();
// Get the user manager
SessionManager sessionManager = webManager.getSessionManager();
// Lets gather what information we are going to display
class regResult {
public JID jid = null;
public long id = -1;
public String type = null;
public String username = null;
public String nickname = null;
public String status = "unavailable";
public String linestatus = "offline";
public String lastLogin = null;
public boolean sessionActive = false;
}
Collection<regResult> regResults = new ArrayList<regResult>();
ArrayList<String> filteropts = new ArrayList<String>();
if (ParamUtils.getParameter(request, "filter[]") != null) {
String[] optlist = ParamUtils.getParameters(request, "filter[]");
for (String opt : optlist) {
filteropts.add(opt);
}
}
else if (webManager.getPageProperty("gateway-registrations", "filterSET", 0) != 0) {
if (webManager.getPageProperty("gateway-registrations", "filterAIM", 0) != 0) { filteropts.add("aim"); }
if (webManager.getPageProperty("gateway-registrations", "filterICQ", 0) != 0) { filteropts.add("icq"); }
if (webManager.getPageProperty("gateway-registrations", "filterMSN", 0) != 0) { filteropts.add("msn"); }
if (webManager.getPageProperty("gateway-registrations", "filterYAHOO", 0) != 0) { filteropts.add("yahoo"); }
if (webManager.getPageProperty("gateway-registrations", "filterIRC", 0) != 0) { filteropts.add("irc"); }
if (webManager.getPageProperty("gateway-registrations", "filterXMPP", 0) != 0) { filteropts.add("xmpp"); }
if (webManager.getPageProperty("gateway-registrations", "filterGTALK", 0) != 0) { filteropts.add("gtalk"); }
if (webManager.getPageProperty("gateway-registrations", "filterSIGNEDON", 0) != 0) { filteropts.add("signedon"); }
}
else {
filteropts.add("aim");
filteropts.add("icq");
filteropts.add("msn");
filteropts.add("yahoo");
filteropts.add("irc");
filteropts.add("gtalk");
filteropts.add("xmpp");
}
webManager.setPageProperty("gateway-registrations", "filterSET", 1);
webManager.setPageProperty("gateway-registrations", "filterAIM", filteropts.contains("aim") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterICQ", filteropts.contains("icq") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterMSN", filteropts.contains("msn") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterYAHOO", filteropts.contains("yahoo") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterIRC", filteropts.contains("irc") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterGTALK", filteropts.contains("gtalk") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterXMPP", filteropts.contains("xmpp") ? 1 : 0);
webManager.setPageProperty("gateway-registrations", "filterSIGNEDON", filteropts.contains("signedon") ? 1 : 0);
int resCount = 0;
for (Registration registration : registrations) {
regResult res = new regResult();
res.id = registration.getRegistrationID();
res.jid = registration.getJID();
res.username = registration.getUsername();
res.nickname = registration.getNickname();
res.type = registration.getTransportType().toString();
if (!filteropts.contains(res.type)) { continue; }
try {
ClientSession clientSession = (ClientSession)sessionManager.getSessions(res.jid.getNode()).toArray()[0];
if (clientSession != null) {
Presence presence = clientSession.getPresence();
if (presence == null) {
// not logged in, leave alone
}
else if (presence.getShow() == Presence.Show.xa) {
res.status = "away";
res.linestatus = "online";
}
else if (presence.getShow() == Presence.Show.away) {
res.status = "away";
res.linestatus = "online";
}
else if (presence.getShow() == Presence.Show.chat) {
res.status = "free_chat";
res.linestatus = "online";
}
else if (presence.getShow() == Presence.Show.dnd) {
res.status = "dnd";
res.linestatus = "online";
}
else if (presence.isAvailable()) {
res.status = "available";
res.linestatus = "online";
}
}
}
catch (Exception e) {
}
if (res.linestatus.equals("offline") && filteropts.contains("signedon")) { continue; }
Date lastLogin = registration.getLastLogin();
res.lastLogin = ((lastLogin != null) ? lastLogin.toString() : "<i>"+LocaleUtils.getLocalizedString("gateway.web.registrations.never", "gateway")+"</i>");
res.sessionActive = false;
try {
plugin.getTransportInstance(res.type).getTransport().getSessionManager().getSession(res.jid);
res.sessionActive = true;
}
catch (Exception e) {
res.sessionActive = false;
}
resCount++;
regResults.add(res);
}
final int DEFAULT_RANGE = 15;
final int[] RANGE_PRESETS = {15, 30, 50, 100};
int start = ParamUtils.getIntParameter(request,"start",0);
int range = ParamUtils.getIntParameter(request,"range",webManager.getRowsPerPage("gateway-registrations", DEFAULT_RANGE));
if (request.getParameter("range") != null) {
webManager.setRowsPerPage("gateway-registrations", range);
}
// paginator vars
int numPages = (int)Math.ceil((double)resCount/(double)range);
int curPage = (start/range) + 1;
int topRange = ((start+range) < resCount) ? (start+range) : resCount;
%>
<html>
<head>
<title><fmt:message key="gateway.web.registrations.title" /></title>
<meta name="pageID" content="gateway-registrations">
<style type="text/css">
<!-- @import url("style/gateways.css"); -->
</style>
<script src="dwr/engine.js" type="text/javascript"></script>
<script src="dwr/util.js" type="text/javascript"></script>
<script src="dwr/interface/ConfigManager.js" type="text/javascript"></script>
<script src="dwr/interface/ConnectionTester.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript" src="scripts/gateways.js"></script>
<script type="text/javascript" >
DWREngine.setErrorHandler(handleError);
window.onerror = handleError;
function handleError(error) {
// swallow errors
}
var lastRegistrationID;
function deleteRegistration(registrationID) {
lastRegistrationID = registrationID;
ConfigManager.deleteRegistration(registrationID, cb_deleteRegistration);
}
function cb_deleteRegistration(statusMsg) {
Effect.Fade("jiveRegistration"+lastRegistrationID);
document.getElementById("regStatusMsg").style.display = "";
if (statusMsg == null) {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-success'><img src='images/success-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.registrations.deletesuccess' /></div>";
}
else {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-error'><img src='images/error-16x16.gif' align='absmiddle' />"+statusMsg+"</div>";
}
setTimeout("to_statusMessage()", 5000);
}
function updateRegistration(registrationID) {
var usernameEntry = DWRUtil.getValue("gatewayUsername"+registrationID);
var passwordEntry = DWRUtil.getValue("gatewayPassword"+registrationID);
if (passwordEntry == "********") {
passwordEntry = null;
}
var nicknameEntry = DWRUtil.getValue("gatewayNickname"+registrationID);
lastRegistrationID = registrationID;
ConfigManager.updateRegistration(registrationID, usernameEntry, passwordEntry, nicknameEntry, cb_updateRegistration);
}
function cb_updateRegistration(statusMsg) {
toggleEdit(lastRegistrationID);
var usernameEntry = DWRUtil.getValue("gatewayUsername"+lastRegistrationID);
document.getElementById("registrationUsername"+lastRegistrationID).innerHTML = usernameEntry;
document.getElementById("regStatusMsg").style.display = "";
if (statusMsg == null) {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-success'><img src='images/success-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.registrations.updatesuccess' /></div>";
}
else {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-error'><img src='images/error-16x16.gif' align='absmiddle' />"+statusMsg+"</div>";
}
setTimeout("to_statusMessage()", 5000);
}
function addRegistration() {
var userEntry = DWRUtil.getValue("newRegistrationUser");
var typeEntry = DWRUtil.getValue("newRegistrationType");
var legacyUsernameEntry = DWRUtil.getValue("newRegistrationLegacyUsername");
var legacyPasswordEntry = DWRUtil.getValue("newRegistrationLegacyPassword");
var legacyNicknameEntry = DWRUtil.getValue("newRegistrationLegacyNickname");
ConfigManager.addRegistration(userEntry, typeEntry, legacyUsernameEntry, legacyPasswordEntry, legacyNicknameEntry, cb_addRegistration);
}
function cb_addRegistration(statusMsg) {
toggleAdd();
document.getElementById("regStatusMsg").style.display = "";
if (statusMsg == null) {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-success'><img src='images/success-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.registrations.addsuccess' /></div>";
}
else {
document.getElementById("regStatusMsg").innerHTML = "<div class='jive-error'><img src='images/error-16x16.gif' align='absmiddle' />"+statusMsg+"</div>";
}
setTimeout("to_statusMessage()", 5000);
}
function to_statusMessage() {
Effect.Fade("regStatusMsg");
}
function pingSession() {
ConnectionTester.pingSession();
setTimeout("pingSession()", 60000); // Every minute
}
setTimeout("pingSession()", 60000); // One minute after first load
</script>
</head>
<body>
<p><fmt:message key="gateway.web.registrations.instructions" /></p>
<div id="regStatusMsg" style="display: none"></div>
<!-- BEGIN add registration -->
<div class="jive-gateway-addregBtn" id="jiveAddRegButton">
<a href="" onClick="toggleAdd(); return false" id="jiveAddRegLink"><fmt:message key="gateway.web.registrations.addnewreg" /></a>
</div>
<div class="jive-gateway-addreg" id="jiveAddRegPanel" style="display: none;">
<div class="jive-gateway-addregPad">
<form action="" name="jive-addRegistration" onSubmit="return false">
<input type="hidden" name="action" value="add" />
<div class="jive-registrations-addJid">
<input type="text" name="newRegistrationUser" id="newRegistrationUser" size="12" maxlength="50" value=""><br>
<strong><fmt:message key="gateway.web.registrations.jid" /></strong>
</div>
<div class="jive-registrations-addGateway">
<select name="newRegistrationType" id="newRegistrationType" size="1">
<option value="0" SELECTED> -- select -- </option>
<% if (trEnabled.get("aim")) { %> <option value="aim"><fmt:message key="gateway.aim.shortservice" /></option> <% } %>
<% if (trEnabled.get("gtalk")) { %> <option value="gtalk"><fmt:message key="gateway.gtalk.shortservice" /></option> <% } %>
<% if (trEnabled.get("icq")) { %> <option value="icq"><fmt:message key="gateway.icq.shortservice" /></option> <% } %>
<% if (trEnabled.get("irc")) { %> <option value="irc"><fmt:message key="gateway.irc.shortservice" /></option> <% } %>
<% if (trEnabled.get("msn")) { %> <option value="msn"><fmt:message key="gateway.msn.shortservice" /></option> <% } %>
<% if (trEnabled.get("xmpp")) { %> <option value="xmpp"><fmt:message key="gateway.xmpp.shortservice" /></option> <% } %>
<% if (trEnabled.get("yahoo")) { %> <option value="yahoo"><fmt:message key="gateway.yahoo.shortservice" /></option> <% } %>
</select><br>
<strong><fmt:message key="gateway.web.registrations.gateway" /></strong>
</div>
<div class="jive-registrations-addUsername">
<input type="text" name="newRegistrationLegacyUsername" id="newRegistrationLegacyUsername" size="12" maxlength="50" value=""><br>
<strong><fmt:message key="gateway.web.registrations.username" /></strong>
</div>
<div class="jive-registrations-addPassword">
<input type="password" name="newRegistrationLegacyPassword" id="newRegistrationLegacyPassword" size="12" maxlength="50" value=""><br>
<strong><fmt:message key="gateway.web.registrations.password" /></strong>
</div>
<div class="jive-registrations-addNickname">
<input type="text" name="newRegistrationLegacyNickname" id="newRegistrationLegacyNickname" size="12" maxlength="50" value=""><br>
<strong><fmt:message key="gateway.web.registrations.nickname" /></strong>
</div>
<div class="jive-registrations-addButtons">
<input type="submit" name="Submit" value="<fmt:message key="global.add" />" class="savechanges" onClick="addRegistration(); return false"> &nbsp;
<input type="reset" name="reset" value="<fmt:message key="global.cancel" />" class="cancel" onClick="toggleAdd();">
</div>
</form>
</div>
</div>
<!-- END add registration -->
<!-- BEGIN registrations table -->
<div class="jive-registrations">
<!-- BEGIN results -->
<div class="jive-registrations-results">
<fmt:message key="gateway.web.registrations.registrations" />: <strong><%= (start+1) %>-<%= topRange %></strong> of <strong><%= resCount %></strong>
</div>
<!-- END results -->
<!-- BEGIN results size (num per page) -->
<div class="jive-registrations-resultsSize"><form action="gateway-registrations.jsp" method="get">
<select name="range" id="range" size="1" onchange="this.form.submit()">
<% for (int rangePreset : RANGE_PRESETS) { %>
<option value="<%= rangePreset %>"<%= (rangePreset== range ? "selected" : "") %>><%= rangePreset %></option>
<% } %>
</select>
<span><fmt:message key="gateway.web.registrations.perpage" /></span>
</form></div>
<!-- END results size -->
<!-- BEGIN pagination -->
<div class="jive-registrations-pagination">
<strong><fmt:message key="gateway.web.registrations.page" />:</strong> &nbsp;
<%
if (numPages > 1 && ((curPage) > 1)) {
%>
<a href="gateway-registrations.jsp?start=<%= ((curPage-2)*range) %>">&lt; <fmt:message key="gateway.web.registrations.prev" /></a>
<%
}
for (int i=0; i<numPages; i++) {
boolean isCurrent = (i+1) == curPage;
if (isCurrent) {
%>
<strong><%= (i+1) %></strong>
<%
}
else {
%>
<a href="gateway-registrations.jsp?start=<%= (i*range) %>"><%= (i+1) %></a>
<%
}
}
if (numPages > 1 && ((curPage) < numPages)) {
%>
<a href="gateway-registrations.jsp?start=<%= (curPage*range) %>"><fmt:message key="gateway.web.registrations.next" /> &gt;</a>
<%
}
%>
</div>
<!-- END pagination -->
<!-- BEGIN gateway filter -->
<form action="gateway-registrations.jsp" name="jive-filterForm">
<div class="jive-gateway-filter" id="jiveGatewayFilters">
<div>
<strong>Filter by:</strong>
<label for="filterAIMcheckbox">
<input type="checkbox" name="filter[]" value="aim" <%= ((filteropts.contains("aim")) ? "checked" : "") %> id="filterAIMcheckbox">
<img src="images/aim.gif" border="0" alt="<fmt:message key="gateway.aim.shortservice" />">
<!--<span><fmt:message key="gateway.aim.shortservice" /></span>-->
</label>
<label for="filterGTALKcheckbox">
<input type="checkbox" name="filter[]" value="gtalk" <%= ((filteropts.contains("gtalk")) ? "checked" : "") %> id="filterGTALKcheckbox">
<img src="images/gtalk.gif" border="0" alt="<fmt:message key="gateway.gtalk.shortservice" />">
<!--<span><fmt:message key="gateway.gtalk.shortservice" /></span>-->
</label>
<label for="filterICQcheckbox">
<input type="checkbox" name="filter[]" value="icq" <%= ((filteropts.contains("icq")) ? "checked" : "") %> id="filterICQcheckbox">
<img src="images/icq.gif" border="0" alt="<fmt:message key="gateway.icq.shortservice" />">
<!--<span><fmt:message key="gateway.icq.shortservice" /></span>-->
</label>
<label for="filterIRCcheckbox">
<input type="checkbox" name="filter[]" value="irc" <%= ((filteropts.contains("irc")) ? "checked" : "") %> id="filterIRCcheckbox">
<img src="images/irc.gif" border="0" alt="<fmt:message key="gateway.irc.shortservice" />">
<!--<span><fmt:message key="gateway.irc.shortservice" /></span>-->
</label>
<label for="filterMSNcheckbox">
<input type="checkbox" name="filter[]" value="msn" <%= ((filteropts.contains("msn")) ? "checked" : "") %> id="filterMSNcheckbox">
<img src="images/msn.gif" border="0" alt="<fmt:message key="gateway.msn.shortservice" />">
<!--<span><fmt:message key="gateway.msn.shortservice" /></span>-->
</label>
<label for="filterXMPPcheckbox">
<input type="checkbox" name="filter[]" value="xmpp" <%= ((filteropts.contains("xmpp")) ? "checked" : "") %> id="filterXMPPcheckbox">
<img src="images/xmpp.gif" border="0" alt="<fmt:message key="gateway.xmpp.shortservice" />">
<!--<span><fmt:message key="gateway.xmpp.shortservice" /></span>-->
</label>
<label for="filterYAHOOcheckbox">
<input type="checkbox" name="filter[]" value="yahoo" <%= ((filteropts.contains("yahoo")) ? "checked" : "") %> id="filterYAHOOcheckbox">
<img src="images/yahoo.gif" border="0" alt="<fmt:message key="gateway.yahoo.shortservice" />">
<!--<span><fmt:message key="gateway.yahoo.shortservice" /></span>-->
</label>
<label for="filterActiveOnly">
<input type="checkbox" name="filter[]" value="signedon" <%= ((filteropts.contains("signedon")) ? "checked" : "") %> id="filterActiveOnly">
<span><fmt:message key="gateway.web.registrations.signedon" /></span>
</label>
<input type="submit" name="submit" value="<fmt:message key="gateway.web.registrations.update" />" class="filterBtn">
</div>
</div>
</form>
<!-- END gateway filter -->
<!-- BEGIN registrations table -->
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th width="20" class="border-left">&nbsp;</th>
<th width="25%"><fmt:message key="gateway.web.registrations.user" /></th>
<th><fmt:message key="gateway.web.registrations.serviceusername" /></th>
<th><fmt:message key="gateway.web.registrations.lastlogin" /></th>
<th width="1%"><div align="center"><fmt:message key="gateway.web.registrations.edit" /></div></th>
<th width="1%" class="border-right"><fmt:message key="gateway.web.registrations.remove" /></th>
</tr>
</thead>
<tbody>
<%
int cnt = 0;
for (regResult result : regResults) {
cnt++;
if (cnt < (start+1)) { continue; }
if (cnt > (start+range)) { continue; }
%>
<tr id="jiveRegistration<%= result.id %>">
<td align="center">
<img src="images/im_<%= result.status %>.gif" alt="<%= result.linestatus %>" border="0"></td>
<td><%= result.jid %></td>
<td><span class="jive-gateway-<%= result.linestatus %> jive-gateway-<%= result.type.toUpperCase() %><%= ((result.sessionActive) ? "on" : "off") %>"><span id="registrationUsername<%= result.id %>"><%= result.username %></span></span></td>
<td><%= result.lastLogin %></td>
<td align="center"><a href="javascript:noop()" onClick="<% if (!trEnabled.get(result.type)) { %>alert('You must enable this transport to modify registrations.'); return false;<% } else { %>toggleEdit(<%= result.id %>); return false<% } %>"><img src="images/edit-16x16.gif" alt="<fmt:message key="global.edit" />" border="0"></a></td>
<td align="center"><a href="javascript:noop()" onClick="<% if (!trEnabled.get(result.type)) { %>alert('You must enable this transport to delete registrations.'); return false;<% } else { %>if (confirm('<fmt:message key="gateway.web.registrations.confirmdelete" />')) { deleteRegistration('<%= result.id %>'); return false; } else { return false; }<% } %>"><img src="images/delete-16x16.gif" alt="<fmt:message key="global.delete" />" border="0"></a></td>
</tr>
<tr id="jiveRegistrationEdit<%= result.id %>" style="display: none">
<td align="center"><img src="images/im_<%= result.status %>.gif" alt="<%= result.status %>" border="0"></td>
<td><%= result.jid %></td>
<td colspan="4"><form method="post" id="editRegistration<%= result.id %>" name="editRegistration<%= result.id %>" action="" onSubmit="return false">
<span class="jive-gateway-<%= result.linestatus %> jive-gateway-<%= result.type.toUpperCase() %>on">
<div class="jive-registrations-editUsername">
<input type="text" name="gatewayUsername<%= result.id %>" id="gatewayUsername<%= result.id %>"size="12" maxlength="50" value="<%= result.username %>"><br>
<strong><fmt:message key="gateway.web.registrations.username" /></strong>
</div>
<div class="jive-registrations-editPassword">
<input type="password" name="gatewayPassword<%= result.id %>" id="gatewayPassword<%= result.id %>"size="12" maxlength="50" value="********"><br>
<strong><fmt:message key="gateway.web.registrations.password" /></strong>
</div>
<div class="jive-registrations-editNickname">
<input type="text" name="gatewayNickname<%= result.id %>%>" id="gatewayNickname<%= result.id %>" size="12" maxlength="50" value="<%= result.nickname %>"><br>
<strong><fmt:message key="gateway.web.registrations.nickname" /></strong>
</div>
<div class="jive-registrations-editButtons">
<input type="submit" name="Submit" value="<fmt:message key="global.save_changes" />" class="savechanges" onClick="updateRegistration('<%= result.id %>'); return false" /> &nbsp;
<input type="reset" name="reset" value="<fmt:message key="global.cancel" />" class="cancel" onClick="toggleEdit(<%= result.id %>);" />
</div>
</span>
</form></td>
</tr>
<%
}
%>
</tbody>
</table>
<!-- BEGIN registrations table -->
<!-- BEGIN pagination -->
<div class="jive-registrations-pagination">
<strong>Page:</strong> &nbsp;
<%
if (numPages > 1 && ((curPage) > 1)) {
%>
<a href="gateway-registrations.jsp?start=<%= ((curPage-2)*range) %>">&lt; Prev</a>
<%
}
for (int i=0; i<numPages; i++) {
boolean isCurrent = (i+1) == curPage;
if (isCurrent) {
%>
<strong><%= (i+1) %></strong>
<%
}
else {
%>
<a href="gateway-registrations.jsp?start=<%= (i*range) %>"><%= (i+1) %></a>
<%
}
}
if (numPages > 1 && ((curPage) < numPages)) {
%>
<a href="gateway-registrations.jsp?start=<%= (curPage*range) %>">Next &gt;</a>
<%
}
%>
</div>
<!-- END pagination -->
</div>
<!-- END registrations table -->
<br clear="all" />
</body>
</html>
<%@ page import="javax.servlet.jsp.JspWriter,
org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.gateway.GatewayPlugin,
org.jivesoftware.openfire.gateway.TransportType"
errorPage="error.jsp"
%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="org.jivesoftware.util.LocaleUtils"%>
<%@ page import="org.dom4j.Element" %>
<%@ page import="org.dom4j.Attribute" %>
<%@ page import="org.jivesoftware.util.Log" %>
<%@ page import="org.dom4j.Document" %>
<%@ page import="org.jivesoftware.util.JiveGlobals" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="org.jivesoftware.openfire.gateway.PermissionManager" %>
<%@ page import="java.util.Collection" %>
<%@ page import="java.util.Iterator" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%
final GatewayPlugin plugin =
(GatewayPlugin) XMPPServer.getInstance().getPluginManager().getPlugin("gateway");
class GatewaySettings {
String description = null;
TransportType gatewayType = null;
boolean gwEnabled = false;
JspWriter out = null;
Integer jsID = 0; // Javascript incrementable id
String connectHost = null;
String connectPort = null;
String userPermText = "[none selected]";
String groupPermText = "[none selected]";
String userPermEntry = "";
String groupPermEntry = "";
Integer globalPermSetting = 1;
GatewaySettings(JspWriter out, GatewayPlugin plugin, TransportType gatewayType,
String desc) {
this.description = desc;
this.gatewayType = gatewayType;
this.gwEnabled = plugin.serviceEnabled(gatewayType.toString());
this.out = out;
getConnectHostAndPort();
getPermissionsList();
}
/**
* Borrowed from http://www.bigbold.com/snippets/posts/show/91
*/
public String join(Collection s, String delimiter) {
StringBuffer buffer = new StringBuffer();
Iterator iter = s.iterator();
while (iter.hasNext()) {
buffer.append(iter.next());
if (iter.hasNext()) {
buffer.append(delimiter);
}
}
return buffer.toString();
}
void getPermissionsList() {
PermissionManager permissionManager = new PermissionManager(this.gatewayType);
ArrayList<String> userList = permissionManager.getAllUsers();
if (userList.size() > 0) {
String joinedString = join(userList, " ");
userPermText = joinedString;
userPermEntry = joinedString;
}
ArrayList<String> groupList = permissionManager.getAllGroups();
if (groupList.size() > 0) {
String joinedString = join(groupList, " ");
groupPermText = joinedString;
groupPermEntry = joinedString;
}
globalPermSetting = JiveGlobals.getIntProperty("plugin.gateway."+this.gatewayType.toString()+".registration", 1);
}
void getConnectHostAndPort() {
// This assumes that you've chosen to keep the connect host and port in a standard
// location ... as a "root level" option in the left or right panel.
Document optConfig = plugin.getOptionsConfig(gatewayType);
if (optConfig == null) {
Log.debug("No options config present for transport.");
return;
}
Element leftPanel = optConfig.getRootElement().element("leftpanel");
Element rightPanel = optConfig.getRootElement().element("rightpanel");
if (leftPanel != null && leftPanel.nodeCount() > 0) {
for (Object nodeObj : leftPanel.elements("item")) {
Element node = (Element) nodeObj;
Attribute type = node.attribute("type");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
if (type == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
continue;
}
Attribute def = node.attribute("default");
String defStr = "";
if (def != null) {
defStr = def.getText();
}
if (type.getText().equals("text") && var.getText().equals("host")) {
this.connectHost = JiveGlobals.getProperty(sysprop.getText(), defStr);
}
if (type.getText().equals("text") && var.getText().equals("port")) {
this.connectPort = JiveGlobals.getProperty(sysprop.getText(), defStr);
}
}
}
if (rightPanel != null && rightPanel.nodeCount() > 0) {
for (Object nodeObj : rightPanel.elements("item")) {
Element node = (Element) nodeObj;
Attribute type = node.attribute("type");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
if (type == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
continue;
}
Attribute def = node.attribute("default");
String defStr = "";
if (def != null) {
defStr = def.getText();
}
if (type.getText().equals("text") && var.getText().equals("host")) {
this.connectHost = JiveGlobals.getProperty(sysprop.getText(), defStr);
}
if (type.getText().equals("text") && var.getText().equals("port")) {
this.connectPort = JiveGlobals.getProperty(sysprop.getText(), defStr);
}
}
}
}
void printConfigNode(Element node) {
try {
Attribute type = node.attribute("type");
if (type.getText().equals("text")) {
// Required fields
Attribute desckey = node.attribute("desckey");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
// Optional fields
Attribute def = node.attribute("default");
Attribute size = node.attribute("size");
Attribute maxlen = node.attribute("maxlength");
if (desckey == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
return;
}
String defStr = "";
if (def != null) {
defStr = def.getText();
}
String descStr = LocaleUtils.getLocalizedString(desckey.getText(), "gateway");
String setting = JiveGlobals.getProperty(sysprop.getText(), defStr);
String inputId = gatewayType.toString() + var.getText();
out.println("<tr valign='middle'>");
out.println("<td align='right' width='1%'><label for='" + inputId + "'>" +
descStr + "</label>:</td>");
out.print("<td><input type='text' id='" + inputId + "' name='" + inputId + "'" +
(size != null ? " size='" + size.getText() + "'" : "") +
(size != null ? " maxlength='" + maxlen.getText() + "'" : "") +
" value='" + setting + "'");
if (var.getText().equals("host")) {
out.print(" onChange='document.getElementById(\"" + gatewayType.toString() +
"testhost\").innerHTML = this.value'");
}
if (var.getText().equals("port")) {
out.print(" onChange='document.getElementById(\"" + gatewayType.toString() +
"testport\").innerHTML = this.value'");
}
out.println("/></td>");
out.println("</tr>");
}
else if (type.getText().equals("toggle")) {
// Required fields
Attribute desckey = node.attribute("desckey");
Attribute var = node.attribute("var");
Attribute sysprop = node.attribute("sysprop");
// Optional fields
Attribute def = node.attribute("default");
if (desckey == null || var == null || sysprop == null) {
Log.error("Missing variable from options config.");
return;
}
boolean defBool = false;
if (def != null && (def.getText().equals("1") || def.getText().equals("true") ||
def.getText().equals("enabled") || def.getText().equals("yes"))) {
defBool = true;
}
String descStr = LocaleUtils.getLocalizedString(desckey.getText(), "gateway");
boolean setting = JiveGlobals.getBooleanProperty(sysprop.getText(), defBool);
String jsStr = gatewayType.toString() + (++jsID);
String checkId = gatewayType.toString() + var.getText();
out.println("<tr valign='top'>");
out.println("<td align='right' width='1%'><input type='checkbox' id='" +
checkId + "' name='" + checkId + "' value='true' " +
(setting ? " checked='checked'" : "") +
" onClick='elem = document.getElementById(\"" + jsStr +
"\"); if (elem) { if (this.checked) { elem.style.display=\"table\"} else { elem.style.display=\"none\"} }'/></td>");
out.print("<td><label for='" + checkId + "'>" + descStr + "</label>");
for (Object itemObj : node.elements("item")) {
Element item = (Element) itemObj;
out.println("<table id='" + jsStr + "' width='100%' style='display: " +
(defBool ? "table" : "none") + "'>");
printConfigNode(item);
out.println("</table>");
}
out.println("</td>");
out.println("</tr>");
}
}
catch (Exception e) {
// Uhm, yeah, that sucks.
Log.error("Error printing config node:", e);
}
}
void printSettingsDialog() {
try {
Document optConfig = plugin.getOptionsConfig(gatewayType);
Element leftPanel = optConfig.getRootElement().element("leftpanel");
Element rightPanel = optConfig.getRootElement().element("rightpanel");
%>
<!-- BEGIN gateway - <%= this.gatewayType.toString().toUpperCase() %> -->
<div <%= ((!this.gwEnabled) ? " class='jive-gateway jive-gatewayDisabled'" : "class='jive-gateway'") %> id="jive<%= this.gatewayType.toString().toUpperCase() %>">
<label for="jive<%= this.gatewayType.toString().toUpperCase() %>checkbox">
<input type="checkbox" name="gateway" value="<%= this.gatewayType.toString().toLowerCase() %>" id="jive<%= this.gatewayType.toString().toUpperCase() %>checkbox" <%= ((this.gwEnabled) ? "checked" : "") %> onClick="ConfigManager.toggleTransport('<%= this.gatewayType.toString().toLowerCase() %>'); checkToggle(jive<%= this.gatewayType.toString().toUpperCase() %>); return true">
<img src="images/<%= this.gatewayType.toString().toLowerCase() %>.gif" alt="" border="0">
<strong><%= this.description %></strong>
</label>
<div class="jive-gatewayButtons">
<a href="#" onclick="togglePanel(jive<%= this.gatewayType.toString().toUpperCase() %>tests); return false" id="jive<%= this.gatewayType.toString().toUpperCase() %>testsLink" <%= ((!this.gwEnabled) ? "style='display:none'" : "") %>><%= LocaleUtils.getLocalizedString("gateway.web.settings.tests", "gateway") %></a>
<a href="#" onclick="togglePanel(jive<%= this.gatewayType.toString().toUpperCase() %>options); return false" id="jive<%= this.gatewayType.toString().toUpperCase() %>optionsLink" <%= ((!this.gwEnabled) ? "style='display:none'" : "") %>><%= LocaleUtils.getLocalizedString("gateway.web.settings.options", "gateway") %></a>
<a href="#" onclick="togglePanel(jive<%= this.gatewayType.toString().toUpperCase() %>perms); return false" id="jive<%= this.gatewayType.toString().toUpperCase() %>permsLink" <%= ((!this.gwEnabled) ? "style='display:none'" : "") %>><%= LocaleUtils.getLocalizedString("gateway.web.settings.permissions", "gateway") %></a>
</div>
</div>
<!-- Tests Window -->
<div class="jive-gatewayPanel" id="jive<%= this.gatewayType.toString().toUpperCase() %>tests" style="display: none;">
<div>
<form id="jive<%= this.gatewayType.toString().toUpperCase() %>testsform" action="" onSubmit="return false">
<span style="font-weight: bold"><%= LocaleUtils.getLocalizedString("gateway.web.settings.connecttohost", "gateway") %>:</span> <span id="<%= this.gatewayType.toString() %>testhost"><%= connectHost %></span><br />
<span style="font-weight: bold"><%= LocaleUtils.getLocalizedString("gateway.web.settings.connecttoport", "gateway") %>:</span> <span id="<%= this.gatewayType.toString() %>testport"><%= connectPort %></span><br />
<span id="<%= this.gatewayType.toString() %>testsresults" class="saveResultsMsg"></span>
<input type="submit" name="submit" value="<%= LocaleUtils.getLocalizedString("gateway.web.settings.testconnection", "gateway") %>" onclick="testConnect('<%= this.gatewayType.toString() %>'); return false" class="jive-formButton">
</form>
</div>
</div>
<!-- Options Window -->
<div class="jive-gatewayPanel" id="jive<%= this.gatewayType.toString().toUpperCase() %>options" style="display: none;">
<div>
<form id="jive<%= this.gatewayType.toString().toUpperCase() %>optionsform" action="" onSubmit="return false">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top">
<td align="left" width="50%">
<%
if (leftPanel != null && leftPanel.nodeCount() > 0) {
out.println("<table border='0' cellpadding='1' cellspacing='2'>");
for (Object nodeObj : leftPanel.elements("item")) {
Element node = (Element)nodeObj;
printConfigNode(node);
}
out.println("</table");
}
else {
out.println("&nbsp;");
}
%>
</td>
<td align="left" width="50%">
<%
if (rightPanel != null && rightPanel.nodeCount() > 0) {
out.println("<table border='0' cellpadding='1' cellspacing='2'>");
for (Object nodeObj : rightPanel.elements("item")) {
Element node = (Element)nodeObj;
printConfigNode(node);
}
out.println("</table>");
}
else {
out.println("&nbsp;");
}
%>
</td>
</tr>
</table>
<span id="<%= this.gatewayType.toString() %>optionsresults" class="saveResultsMsg"></span>
<input type="submit" name="submit" value="<%= LocaleUtils.getLocalizedString("gateway.web.settings.saveoptions", "gateway") %>" onclick="saveOptions('<%= this.gatewayType.toString() %>'); return false" class="jive-formButton">
<input type="reset" name="cancel" value="<%= LocaleUtils.getLocalizedString("gateway.web.settings.cancelchanges", "gateway") %>" onclick="cancelOptions('<%= this.gatewayType.toString() %>'); return true" class="jive-formButton">
</form>
</div>
</div>
<!-- Permissions Window -->
<div class="jive-gatewayPanel" id="jive<%= this.gatewayType.toString().toUpperCase() %>perms" style="display: none;">
<div>
<form id="jive<%= this.gatewayType.toString().toUpperCase() %>permsform" action="" onSubmit="return false">
<input type="radio" name="<%= this.gatewayType.toString() %>userreg" value="all" onClick="hideSpecificChoices('<%= this.gatewayType.toString() %>')" <%= (this.globalPermSetting == 1 ? "checked='checked'" : "") %> /> <%= LocaleUtils.getLocalizedString("gateway.web.settings.registerall", "gateway") %><br>
<input type="radio" name="<%= this.gatewayType.toString() %>userreg" value="specific" onClick="showSpecificChoices('<%= this.gatewayType.toString() %>')" <%= (this.globalPermSetting == 2 ? "checked='checked'" : "") %> /> <%= LocaleUtils.getLocalizedString("gateway.web.settings.registersome", "gateway") %><br>
<div id="<%= this.gatewayType.toString() %>userreg_specific" style="<%= (this.globalPermSetting == 2 ? "" : "display: none; ") %>margin: 0; padding: 0; font-size: 80%">
<table border="0" cellpadding="0" cellspacing="0" style="margin-left: 30.0px" width='100%'>
<tr valign="top">
<td align="left" style="padding-right: 15.0px" width='50%'>
<span style="font-weight: bold"><%= LocaleUtils.getLocalizedString("gateway.web.settings.users", "gateway") %></span> <a href="javascript:noop()" onClick="activateModifyUsers('<%= this.gatewayType.toString() %>'); return false">(Modify Users)</a><br />
<div id="<%= this.gatewayType.toString() %>userpermtextdiv" style="margin: 0px; padding: 0px" class='permissionListDiv'><span id="<%= this.gatewayType.toString() %>userpermtext"><%= this.userPermText %></span></div>
<div id="<%= this.gatewayType.toString() %>userpermentrydiv" style="margin: 0px; padding: 0px; display:none" class='permissionListDiv'><textarea style="margin: 0px" class='permissionListTextArea' rows="5" cols="20" id="<%= this.gatewayType.toString() %>userpermentry" name="<%= this.gatewayType.toString() %>userpermentry"><%= this.userPermEntry %></textarea></div>
</td>
<td align="left" style="margin-left: 15.0px" width='50%'>
<span style="font-weight: bold"><%= LocaleUtils.getLocalizedString("gateway.web.settings.groups", "gateway") %></span> <a href="javascript:noop()" onClick="activateModifyGroups('<%= this.gatewayType.toString() %>'); return false">(Modify Groups)</a><br />
<div id="<%= this.gatewayType.toString() %>grouppermtextdiv" style="margin: 0px; padding: 0px" class='permissionListDiv'><span id="<%= this.gatewayType.toString() %>grouppermtext"><%= this.groupPermText %></span></div>
<div id="<%= this.gatewayType.toString() %>grouppermentrydiv" style="margin: 0px; padding: 0px; display:none" class='permissionListDiv'><textarea style="margin: 0px" class='permissionListTextArea' rows="5" cols="20" id="<%= this.gatewayType.toString() %>grouppermentry" name="<%= this.gatewayType.toString() %>grouppermentry"><%= this.groupPermEntry %></textarea></div>
</td>
</tr>
</table>
</div>
<input type="radio" name="<%= this.gatewayType.toString() %>userreg" value="manual" onClick="hideSpecificChoices('<%= this.gatewayType.toString() %>')" <%= (this.globalPermSetting == 3 ? "checked='checked'" : "") %> /> <%= LocaleUtils.getLocalizedString("gateway.web.settings.registernone", "gateway") %><br>
<span id="<%= this.gatewayType.toString() %>permsresults" class="saveResultsMsg"></span>
<input type="submit" name="submit" value="<%= LocaleUtils.getLocalizedString("gateway.web.settings.savepermissions", "gateway") %>" onclick="savePermissions('<%= this.gatewayType.toString() %>'); return false" class="jive-formButton">
<input type="reset" name="cancel" value="<%= LocaleUtils.getLocalizedString("gateway.web.settings.cancelchanges", "gateway") %>" onclick="cancelPermissions('<%= this.gatewayType.toString() %>'); return true" class="jive-formButton">
</form>
</div>
</div>
<!-- END gateway - <%= this.gatewayType.toString().toUpperCase() %> -->
<%
}
catch (Exception e) {
// Uhm, yeah, that sucks.
Log.error("Error printing settings section:", e);
}
}
}
GatewaySettings aimSettings = new GatewaySettings(out, plugin, TransportType.aim, LocaleUtils.getLocalizedString("gateway.aim.service", "gateway"));
GatewaySettings gtalkSettings = new GatewaySettings(out, plugin, TransportType.gtalk, LocaleUtils.getLocalizedString("gateway.gtalk.service", "gateway"));
GatewaySettings icqSettings = new GatewaySettings(out, plugin, TransportType.icq, LocaleUtils.getLocalizedString("gateway.icq.service", "gateway"));
GatewaySettings ircSettings = new GatewaySettings(out, plugin, TransportType.irc, LocaleUtils.getLocalizedString("gateway.irc.service", "gateway"));
GatewaySettings msnSettings = new GatewaySettings(out, plugin, TransportType.msn, LocaleUtils.getLocalizedString("gateway.msn.service", "gateway"));
GatewaySettings xmppSettings = new GatewaySettings(out, plugin, TransportType.xmpp, LocaleUtils.getLocalizedString("gateway.xmpp.service", "gateway"));
GatewaySettings yahooSettings = new GatewaySettings(out, plugin, TransportType.yahoo, LocaleUtils.getLocalizedString("gateway.yahoo.service", "gateway"));
%>
<html>
<head>
<title><fmt:message key="gateway.web.settings.title" /></title>
<meta name="pageID" content="gateway-settings">
<style type="text/css">
<!-- @import url("style/gateways.css"); -->
</style>
<script src="dwr/engine.js" type="text/javascript"></script>
<script src="dwr/util.js" type="text/javascript"></script>
<script src="dwr/interface/ConfigManager.js" type="text/javascript"></script>
<script src="dwr/interface/ConnectionTester.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript" src="scripts/gateways.js"></script>
<script type="text/javascript" >
DWREngine.setErrorHandler(handleError);
window.onerror = handleError;
function handleError(error) {
// swallow errors
}
var settings;
// If you add new option types, you to the transport option configs, you will also need
// to add the option 'var' ids here.
var optionTypes = new Array(
"host",
"port",
"encoding"
);
var testTransportID = null;
function saveOptions(transportID) {
var transportSettings = new Object();
for (var x in optionTypes) {
var optType = optionTypes[x];
var optionId = transportID+optType;
var testoption = document.getElementById(optionId);
if (testoption != null) {
transportSettings[optType] = DWRUtil.getValue(optionId);
}
}
ConfigManager.saveSettings(transportID, transportSettings);
document.getElementById(transportID+"optionsresults").style.display = "";
document.getElementById(transportID+"optionsresults").innerHTML = "<span class='successresults'><img src='images/success-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.settings.settingssaved' /></span>";
setTimeout("to_saveOptions('"+transportID+"')", 5000);
}
function cancelOptions(transportID) {
document.getElementById(transportID+"optionsresults").style.display = "";
document.getElementById(transportID+"optionsresults").innerHTML = "<span class='warningresults'><img src='images/warning-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.settings.cancelledchanges' /></span>";
setTimeout("to_saveOptions('"+transportID+"')", 5000);
}
function to_saveOptions(transportID) {
Effect.Fade(transportID+"optionsresults");
}
function testConnect(transportID) {
testTransportID = transportID;
ConnectionTester.testConnection(DWRUtil.getValue(transportID+"testhost"),
DWRUtil.getValue(transportID+"testport"), cb_testConnect);
}
function cb_testConnect(result) {
document.getElementById(testTransportID+"testsresults").style.display = "";
if (result) {
document.getElementById(testTransportID+"testsresults").innerHTML = "<span class='successresults'><img src='images/success-16x16.gif' alt='' align='absmiddle' /><fmt:message key='gateway.web.settings.success' /></span>";
}
else {
document.getElementById(testTransportID+"testsresults").innerHTML = "<span class='failureresults'><img src='images/failure-16x16.gif' alt='' align='absmiddle' /><fmt:message key='gateway.web.settings.failed' /></span>";
}
setTimeout("to_testConnect('"+testTransportID+"')", 5000);
testTransportID = null;
}
function to_testConnect(transportID) {
Effect.Fade(transportID+"testsresults");
}
var lastUserList;
var lastGroupList;
var lastTransportID;
function savePermissions(transportID) {
var userEntry = DWRUtil.getValue(transportID+"userpermentry");
var groupEntry = DWRUtil.getValue(transportID+"grouppermentry");
var globalSettingStr = DWRUtil.getValue(transportID+"userreg");
var globalSetting = 1; // Allow all as default
if (globalSettingStr == "all") {
globalSetting = 1;
}
else if (globalSettingStr == "specific") {
globalSetting = 2;
}
else if (globalSettingStr == "manual") {
globalSetting = 3;
}
var userList = userEntry.split(/\s+/);
var groupList = groupEntry.split(/\s+/);
lastUserList = userList;
lastGroupList = groupList;
lastTransportID = transportID;
ConfigManager.savePermissions(transportID, globalSetting, userList, groupList, cb_savePermissions);
}
function cb_savePermissions(errorList) {
var userList = lastUserList;
var groupList = lastGroupList;
var transportID = lastTransportID;
if (errorList != null && errorList.length > 0) {
var errUsers = new Array();
var errGroups = new Array();
for (i = 0; i < errorList.length; i++) {
if (errorList[i].charAt(0) == "@") {
var grpName = errorList[i].substr(1, (errorList[i].length-1));
errGroups.push(grpName);
for (j = 0; j < groupList.length; j++) {
if (groupList[j] == grpName) {
groupList.splice(j, 1);
break;
}
}
}
else {
var userName = errorList[i];
errUsers.push(userName);
for (j = 0; j < userList.length; j++) {
if (userList[j] == userName) {
userList.splice(j, 1);
break;
}
}
}
}
var errMsg = "";
if (errUsers.length > 0) {
errMsg = errMsg + "\nThe following users were not valid and were ignored:\n" + errUsers.join("\n") + "\n";
}
if (errGroups.length > 0) {
errMsg = errMsg + "\nThe following groups were not valid and were ignored:\n" + errGroups.join("\n") + "\n";
}
alert(errMsg);
}
for (i = 0; i < userList.length; i++) {
var charPos = userList[i].indexOf("@");
if (charPos >= 0) {
userList[i] = userList[i].substr(0, charPos);
}
}
document.getElementById(transportID+"userpermtext").innerHTML = (userList.length > 0 ? userList.join(" ") : "[none selected]");
document.getElementById(transportID+"userpermentry").value = userList.join(" ");
document.getElementById(transportID+"grouppermtext").innerHTML = (groupList.length > 0 ? groupList.join(" ") : "[none selected]");
document.getElementById(transportID+"grouppermentry").value = groupList.join(" ");
deactivateModifyUsers(transportID);
deactivateModifyGroups(transportID);
document.getElementById(transportID+"permsresults").style.display = "";
document.getElementById(transportID+"permsresults").innerHTML = "<span class='successresults'><img src='images/success-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.settings.permissionssaved' /></span>";
setTimeout("to_savePermissions('"+transportID+"')", 5000);
}
function cancelPermissions(transportID) {
deactivateModifyUsers(transportID);
deactivateModifyGroups(transportID);
document.getElementById(transportID+"permsresults").style.display = "";
document.getElementById(transportID+"permsresults").innerHTML = "<span class='warningresults'><img src='images/warning-16x16.gif' align='absmiddle' /><fmt:message key='gateway.web.settings.cancelledchanges' /></span>";
setTimeout("to_savePermissions('"+transportID+"')", 5000);
}
function to_savePermissions(transportID) {
Effect.Fade(transportID+"permsresults");
}
function activateModifyUsers(transportID) {
var textElem = document.getElementById(transportID+"userpermtextdiv");
var entryElem = document.getElementById(transportID+"userpermentrydiv");
if (textElem.style.display != "none") {
Effect.SlideUp(textElem,{duration: .4});
}
if (entryElem.style.display == "none") {
Effect.SlideDown(entryElem, {duration: .4, delay: .5});
}
}
function deactivateModifyUsers(transportID) {
var textElem = document.getElementById(transportID+"userpermtextdiv");
var entryElem = document.getElementById(transportID+"userpermentrydiv");
if (entryElem.style.display != "none") {
Effect.SlideUp(entryElem,{duration: .4});
}
if (textElem.style.display == "none") {
Effect.SlideDown(textElem, {duration: .4, delay: .5});
}
}
function activateModifyGroups(transportID) {
var textElem = document.getElementById(transportID+"grouppermtextdiv");
var entryElem = document.getElementById(transportID+"grouppermentrydiv");
if (textElem.style.display != "none") {
Effect.SlideUp(textElem,{duration: .4});
}
if (entryElem.style.display == "none") {
Effect.SlideDown(entryElem, {duration: .4, delay: .5});
}
}
function deactivateModifyGroups(transportID) {
var textElem = document.getElementById(transportID+"grouppermtextdiv");
var entryElem = document.getElementById(transportID+"grouppermentrydiv");
if (entryElem.style.display != "none") {
Effect.SlideUp(entryElem,{duration: .4});
}
if (textElem.style.display == "none") {
Effect.SlideDown(textElem, {duration: .4, delay: .5});
}
}
function hideSpecificChoices(transportID) {
var targElement = document.getElementById(transportID+"userreg_specific");
if (targElement.style.display != "none") {
Effect.toggle(targElement,'slide', {duration: .4});
}
}
function showSpecificChoices(transportID) {
var targElement = document.getElementById(transportID+"userreg_specific");
if (targElement.style.display == "none") {
Effect.toggle(targElement,'slide', {duration: .4});
}
}
function pingSession() {
ConnectionTester.pingSession();
setTimeout("pingSession()", 60000); // Every minute
}
setTimeout("pingSession()", 60000); // One minute after first load
</script>
</head>
<body>
<p><fmt:message key="gateway.web.settings.instructions" /></p>
<form action="" name="gatewayForm">
<% aimSettings.printSettingsDialog(); %>
<% ircSettings.printSettingsDialog(); %>
<% msnSettings.printSettingsDialog(); %>
<br><br>
<div id="jive-title"><fmt:message key="gateway.web.settings.unstable.title" /></div>
<p><fmt:message key="gateway.web.settings.unstable.notice" /></p>
<% gtalkSettings.printSettingsDialog(); %>
<% icqSettings.printSettingsDialog(); %>
<% xmppSettings.printSettingsDialog(); %>
<% yahooSettings.printSettingsDialog(); %>
</form>
<br clear="all">
</body>
</html>
/*
togglePanel function
This is for showing and hiding the gateway options and permissions panels.
This toggles toggles an individual panel (slides up and down), or switches
between the two if one's already open.
*/
var lastID = "";
function togglePanel(thisID) {
var activeLink = thisID.id+"Link";
if (lastID != "" && lastID != thisID) {
var oldLink = lastID.id+"Link";
if ($(thisID).style.display != 'none' && $(lastID).style.display == 'none') {
Effect.toggle($(thisID),'slide', {duration: .4});
$(activeLink).className = "";
} else if ($(thisID).style.display == 'none' && $(lastID).style.display != 'none') {
Effect.toggle($(lastID),'slide', {duration: .4});
$(oldLink).className = "";
Effect.toggle($(thisID),'slide', {duration: .4, delay: .5});
$(activeLink).className = "jive-gatewayButtonOn";
} else {
Effect.toggle($(thisID),'slide', {duration: .4});
$(activeLink).className = "jive-gatewayButtonOn";
}
}
else {
if ($(thisID).style.display != 'none') {
Effect.toggle($(thisID),'slide', {duration: .4});
$(activeLink).className = "";
} else {
Effect.toggle($(thisID),'slide', {duration: .4});
$(activeLink).className = "jive-gatewayButtonOn";
}
}
lastID = thisID;
}
/*
checkToggle function
this toggles the appearance and options for the gateways. When a user
unchecks a gateway the box goes grey panels aren't accessible.
*/
function checkToggle(theID) {
var theCheckbox = theID.id+"checkbox";
var testLink = theID.id+"testsLink";
var optsLink = theID.id+"optionsLink";
var permLink = theID.id+"permsLink";
var testPanel = theID.id+"tests";
var optsPanel = theID.id+"options";
var permPanel = theID.id+"perms";
if ($(theCheckbox).checked) {
$(theID).className = "jive-gateway";
$(testLink).style.display = 'block';
$(optsLink).style.display = 'block';
$(permLink).style.display = 'block';
} else {
$(theID).className = "jive-gateway jive-gatewayDisabled";
$(testLink).style.display = 'none';
$(optsLink).style.display = 'none';
$(permLink).style.display = 'none';
/* fix the panels so they roll up and the buttons go back to default states */
$(testLink).className = "";
$(optsLink).className = "";
$(permLink).className = "";
if ($(optsPanel).style.display != 'none') {
Effect.toggle($(optsPanel), 'slide', {duration: .1});
} else if ($(permPanel).style.display != 'none') {
Effect.toggle($(permPanel), 'slide', {duration: .1});
} else if ($(testPanel).style.display != 'none') {
Effect.toggle($(testPanel), 'slide', {duration: .1});
}
}
}
/*
toggleAdd function
This is the function that shows / hides the add registration form
*/
function toggleAdd(theID) {
var jiveAddRegPanel = document.getElementById("jiveAddRegPanel");
var jiveAddRegButton = document.getElementById("jiveAddRegButton");
var jiveAddRegLink = document.getElementById("jiveAddRegLink");
if ($(jiveAddRegPanel).style.display != 'none') {
Effect.SlideUp($(jiveAddRegPanel), {duration: .2})
$(jiveAddRegButton).className = "jive-gateway-addregBtn";
$(jiveAddRegLink).innerHTML = "Add a new registration";
} else if ($(jiveAddRegPanel).style.display == 'none') {
Effect.SlideDown($(jiveAddRegPanel), {duration: .2})
$(jiveAddRegButton).className = "jive-gateway-addregBtn jive-gateway-cancelAdd";
$(jiveAddRegLink).innerHTML = "Cancel adding new registration";
}
}
/*
toggleEdit function
This is the function that shows / hides the edit fields for an existing registration
*/
function toggleEdit(theNum) {
var normalRow = "jiveRegistration"+theNum;
var editRow = "jiveRegistrationEdit"+theNum;
if ($(editRow).style.display != 'none') {
$(editRow).className = "jive-registrations-edit";
$(editRow).style.display = 'none';
$(normalRow).className = "jive-registrations-normal";
} else if ($(editRow).style.display == 'none') {
$(normalRow).className = "jive-registrations-normalHidden";
$(editRow).className = "jive-registrations-editVisible";
Effect.Appear($(editRow), {duration: .2});
}
}
/* ********************************************* */
/* gateway block (surrounds each gateway listed) */
/* ********************************************* */
.jive-gateway {
display: block;
position: relative;
width: 550px;
background-color: #f3f7fa;
border: 1px solid #dcdcdc;
margin: 15px 0px 0px 0px;
padding: 4px 6px 4px 7px;
overflow: hidden;
-moz-border-radius: 4px;
}
.jive-gateway label {
display: block;
float: left;
padding-top: 2px;
}
.jive-gateway label img {
float: left;
margin: 0px 4px 0px 3px;
}
.jive-gateway label input {
float: left;
}
.jive-gateway label strong {
float: left;
padding-top: 1px;
}
.jive-gatewayButtons {
display: block;
position: relative;
width: auto;
float: right;
clear: none;
right: 0px;
margin-top: 0px;
}
.jive-gatewayButtons a {
display: block;
float: left;
border: 1px solid #f3f7fa;
padding: 2px 10px 2px 18px;
margin: 0px 5px 0px 0px;
background: url('../images/twisty_closed_9x9.gif') no-repeat left;
background-position: 6px;
color: #34679a;
}
.jive-gatewayButtons a:hover {
border: 1px solid #dcdcdc;
}
a.jive-gatewayButtonOn {
border: 1px solid #dcdcdc;
background: #ffffff url('../images/twisty_opened_9x9.gif') no-repeat left;
background-position: 6px;
}
/* disabled panel, when a gateway isn't selected */
.jive-gatewayDisabled {
background-color: #fcfcfc;
}
.jive-gatewayDisabled .jive-gatewayButtons a {
border: 1px solid #fcfcfc;
background: url('../images/twisty_inactive_9x9.gif') no-repeat left;
background-position: 6px;
color: #999999;
text-decoration: none;
cursor: default;
}
.jive-gatewayDisabled .jive-gatewayButtons a:hover {
border: 1px solid #fcfcfc;
}
/* ********************************************************* */
/* gateway preferences panels (both options and permissions) */
/* ********************************************************* */
.jive-gatewayPanel {
display: block;
position: relative;
width: 495px;
background: #f7f5f0 url('../images/gateway-options-panel-grad.gif') repeat-x top;
border: 1px solid #dcdcdc;
border-top: none;
margin: 0px 0px 5px 45px;
padding: 0px;
overflow: hidden;
-moz-border-radius: 0px 0px 4px 4px;
}
.jive-gatewayPanel div {
padding: 14px 15px 5px 15px;
}
.jive-gatewayPanel div form {
margin: 0px;
padding: 0px;
}
.jive-formButton {
margin: 10px 5px 5px 0px;
vertical-align: middle;
}
.saveResultsMsg {
margin: 10px 5px 5px 0px;
padding: 0px;
padding-top: 2px;
font-weight: bold;
float: right;
}
.saveResultsMsg .successresults {
border: 1.0px solid #009900;
background-color: #aaffaa;
color: #009900;
padding: 3.0px;
}
.saveResultsMsg .successresults img {
margin-right: 3px;
margin-bottom: 2px;
}
.saveResultsMsg .failureresults {
border: 1.0px solid #ff0000;
background-color: #ffaaaa;
color: #ff0000;
padding: 3.0px;
}
.saveResultsMsg .failureresults img {
margin-right: 3px;
margin-bottom: 2px;
}
.saveResultsMsg .warningresults {
border: 1.0px solid #D9B04C;
background-color: #FFE9B2;
color: #915a15;
padding: 3.0px;
}
.saveResultsMsg .warningresults img {
margin-right: 3px;
margin-bottom: 2px;
}
.permissionListTextArea {
font-size: 70%;
margin: 0px;
padding: 1px;
}
.permissionListDiv {
padding: 0px;
margin: 0px;
}
.permissionListDiv span {
padding: 0px;
margin: 0px;
}
/* ******************************************** */
/* gateway filter (top of 'regsitrations' page) */
/* ******************************************** */
.jive-gateway-filter {
display: block;
position: relative;
float: left;
clear: both;
background-color: #f6f6f7;
border: 1px solid #dcdcdc;
margin: 5px 0px 5px 0px;
padding: 0px;
-moz-border-radius: 4px;
}
.jive-gateway-filter div {
display: block;
position: relative;
float: left;
padding: 3px 6px 4px 5px;
}
.jive-gateway-filter strong {
display: block;
float: left;
padding-top: 3px;
}
.jive-gateway-filter label {
display: block;
float: left;
margin: 2px 10px 0px 15px;
}
.jive-gateway-filter label input {
float: left;
}
.jive-gateway-filter label img {
float: left;
margin: 0px 4px 0px 2px;
}
.jive-gateway-filter label span {
float: left;
padding-top: 1px;
}
.jive-gateway-filter input.filterBtn {
float: right;
}
/* the below is for a future feature */
.jive-gateway-filter-dropdownLink {
display: block;
float: left;
margin-left: 15px;
}
.jive-gateway-filter-dropdown {
display: block;
position: absolute;
margin: 0px 0px 0px 410px;
padding: 10px;
background-color: #f3f7fa;
border: 1px solid #dcdcdc;
-moz-border-radius: 3px;
z-index: 200;
}
/* *********************************************** */
/* registrations, big block table of registrations */
/* *********************************************** */
.jive-registrations {
display: block;
position: relative;
float: left;
width: 97%;
background-color: #fff;
border: 1px solid #dcdcdc;
margin: 16px 0px 20px 0px;
padding: 8px 6px 10px 7px;
overflow: hidden;
-moz-border-radius: 4px;
}
.jive-registrations a {
color: #34679a;
}
.jive-registrations form {
margin: 0px;
padding: 0px;
}
.jive-registrations-results {
display: block;
position: relative;
float: left;
font-size: 1.2em;
padding-left: 3px;
word-spacing: 3px;
}
.jive-registrations-resultsSize {
display: block;
position: relative;
float: left;
font-size: .9em;
padding-left: 28px;
}
.jive-registrations-resultsSize select {
float: left;
}
.jive-registrations-resultsSize span {
float: left;
margin: 2px 0px 0px 4px;
}
.jive-registrations-pagination {
float: right;
font-size: .9em;
padding-right: 6px;
word-spacing: 2px;
}
.jive-registrations table {
display: block;
float: left;
width: 100%;
padding: 3px 5px 3px 5px;
margin: 5px 0px 5px 0px;
}
.jive-registrations table thead th {
text-align: left;
font-size: .75em;
padding-right: 5px;
padding: 3px;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background-color: #f3f7fa;
}
.jive-registrations table thead th.border-left {
border-left: 1px solid #ccc;
}
.jive-registrations table thead th.border-right {
border-right: 1px solid #ccc;
}
.jive-registrations table tbody td {
font-size: .75em;
padding-right: 5px;
padding: 3px;
border-bottom: 1px solid #ccc;
vertical-align: top;
}
/* ****************************** */
/* user's gateway presence styles */
/* ****************************** */
.jive-gateway-online {
display: block;
float: left;
color: #000;
padding: 1px 0px 2px 25px;
}
.jive-gateway-offline {
display: block;
float: left;
color: #666;
padding: 1px 0px 2px 25px;
}
.jive-gateway-AIMon {
background: url(../images/aim.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-AIMoff {
background: url(../images/aim-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-GTALKon {
background: url(../images/gtalk.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-GTALKoff {
background: url(../images/gtalk-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-ICQon {
background: url(../images/icq.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-ICQoff {
background: url(../images/icq-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-IRCon {
background: url(../images/irc.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-IRCoff {
background: url(../images/irc-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-MSNon {
background: url(../images/msn.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-MSNoff {
background: url(../images/msn-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-XMPPon {
background: url(../images/xmpp.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-XMPPoff {
background: url(../images/xmpp-gray.gif) no-repeat left;
background-position: 2px 1px;
}
.jive-gateway-YAHOOon {
background: url(../images/yahoo.gif) no-repeat left;
background-position: 0px 1px;
}
.jive-gateway-YAHOOoff {
background: url(../images/yahoo-gray.gif) no-repeat left;
background-position: 0px 1px;
}
/* *************************** */
/* edit gateway registrations */
/* *************************** */
table tr.jive-registrations-normal {
display: table-row;
}
table tr.jive-registrations-normalHidden {
display: none;
}
table tr.jive-registrations-edit {
display: none;
}
table tr.jive-registrations-editVisible {
/*display: table-row;*/
}
tr.jive-registrations-edit, tr.jive-registrations-editVisible td {
background-color: #f6f6f6;
}
.jive-registrations-editUsername, .jive-registrations-editPassword, .jive-registrations-editNickname {
float: left;
}
.jive-registrations-editUsername strong, .jive-registrations-editPassword strong, .jive-registrations-editNickname strong {
font-size: .9em;
color: #203050;
}
.jive-registrations-editUsername input, .jive-registrations-editPassword input, .jive-registrations-editNickname input {
width: 110px;
height: 21px;
border: 1px solid #888888;
padding-left: 2px;
}
.jive-registrations-editPassword {
padding-left: 8px;
}
.jive-registrations-editNickname {
padding-left: 8px;
}
.jive-registrations-editButtons {
float: left;
padding-left: 15px;
}
/* *************************** */
/* add a gateway registration */
/* *************************** */
.jive-gateway-addregBtn {
display: block;
position: relative;
float: left;
margin: 10px 0px 8px 0px;
}
.jive-gateway-addregBtn a {
display: block;
float: left;
background: url('../images/add-16x16.gif') no-repeat left;
padding-left: 20px;
color: #34679a;
font-weight: bold;
}
.jive-gateway-cancelAdd a {
background: url('../images/forbidden-16x16.gif') no-repeat left;
}
.jive-gateway-addreg {
display: block;
position: relative;
float: left;
clear: both;
width: 97%;
background-color: #f3f7fa;
border: 1px solid #dcdcdc;
margin: 0px 0px 20px 0px;
padding: 0px;
-moz-border-radius: 4px;
white-space: nowrap;
}
.jive-gateway-addreg div {
float: left;
}
.jive-gateway-addregPad {
padding: 10px 5px 3px 15px;
white-space: nowrap;
}
.jive-gateway-addreg strong {
font-size: .9em;
color: #203050;
}
.jive-registrations-addJid input,
.jive-registrations-addGateway select,
.jive-registrations-addUsername input,
.jive-registrations-addPassword input,
.jive-registrations-addNickname input{
width: 130px;
height: 20px;
border: 1px solid #888888;
margin: 2px 7px 0px 0px;
padding: 0px 0px 0px 1px;
}
.jive-registrations-addButtons {
margin: 0px 5px 0px 10px;
white-space: nowrap;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment