From a1dff2cb8d33b17bc5981f1638cd50266713e98f Mon Sep 17 00:00:00 2001 From: Frankie B Date: Thu, 9 May 2024 23:19:29 +0100 Subject: [PATCH] Add existing source + chat invite handling --- .github/README.md | 24 + .github/changes.txt | 32 + .gitignore | 5 + LICENSE | 340 +++++++ build.xml | 118 +++ doc/toc.txt | 489 +++++++++ jaimlib.iml | 11 + src/com/wilko/jaim/.nbattrs | 49 + src/com/wilko/jaim/Buddy.java | 88 ++ .../wilko/jaim/BuddyUpdateTocResponse.java | 210 ++++ src/com/wilko/jaim/ChatInviteTocResponse.java | 103 ++ src/com/wilko/jaim/ConfigTocResponse.java | 194 ++++ .../wilko/jaim/ConnectionLostTocResponse.java | 50 + src/com/wilko/jaim/ErrorTocResponse.java | 145 +++ src/com/wilko/jaim/EvilTocResponse.java | 117 +++ src/com/wilko/jaim/FLAPDataFrame.java | 76 ++ src/com/wilko/jaim/FLAPErrorFrame.java | 51 + src/com/wilko/jaim/FLAPFrame.java | 119 +++ src/com/wilko/jaim/FLAPFrameException.java | 51 + src/com/wilko/jaim/FLAPFrameFactory.java | 69 ++ src/com/wilko/jaim/FLAPInputFrame.java | 76 ++ src/com/wilko/jaim/FLAPKeepAliveFrame.java | 56 ++ src/com/wilko/jaim/FLAPSignoffFrame.java | 52 + src/com/wilko/jaim/FLAPSignonFrame.java | 90 ++ src/com/wilko/jaim/GenericTocResponse.java | 85 ++ src/com/wilko/jaim/GotoTocResponse.java | 106 ++ src/com/wilko/jaim/Group.java | 100 ++ src/com/wilko/jaim/IMTocResponse.java | 122 +++ src/com/wilko/jaim/JaimConnection.java | 926 ++++++++++++++++++ src/com/wilko/jaim/JaimEvent.java | 42 + src/com/wilko/jaim/JaimEventListener.java | 40 + src/com/wilko/jaim/JaimException.java | 51 + src/com/wilko/jaim/JaimStateException.java | 44 + src/com/wilko/jaim/JaimTimeoutException.java | 45 + .../wilko/jaim/LoginCompleteTocResponse.java | 50 + src/com/wilko/jaim/NickTocResponse.java | 82 ++ src/com/wilko/jaim/SignOnTocResponse.java | 80 ++ src/com/wilko/jaim/TocAddBuddyCommand.java | 67 ++ src/com/wilko/jaim/TocAddDenyCommand.java | 67 ++ src/com/wilko/jaim/TocAddPermitCommand.java | 67 ++ src/com/wilko/jaim/TocChatJoinCommand.java | 53 + src/com/wilko/jaim/TocCommand.java | 43 + .../jaim/TocErrorDescriptions.properties | 28 + src/com/wilko/jaim/TocEvilCommand.java | 61 ++ src/com/wilko/jaim/TocGetInfoCommand.java | 70 ++ src/com/wilko/jaim/TocIMCommand.java | 58 ++ src/com/wilko/jaim/TocInitDoneCommand.java | 50 + src/com/wilko/jaim/TocResponse.java | 49 + src/com/wilko/jaim/TocResponseFactory.java | 82 ++ src/com/wilko/jaim/TocResponseHandler.java | 44 + src/com/wilko/jaim/TocSetAwayCommand.java | 56 ++ src/com/wilko/jaim/TocSetConfigCommand.java | 74 ++ src/com/wilko/jaim/TocSetIdleCommand.java | 53 + src/com/wilko/jaim/TocSetInfoCommand.java | 56 ++ src/com/wilko/jaim/TocSignonCommand.java | 63 ++ src/com/wilko/jaim/Utils.java | 143 +++ src/com/wilko/jaimtest/.nbattrs | 7 + src/com/wilko/jaimtest/JaimTest.java | 243 +++++ 58 files changed, 5822 insertions(+) create mode 100644 .github/README.md create mode 100644 .github/changes.txt create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 build.xml create mode 100644 doc/toc.txt create mode 100644 jaimlib.iml create mode 100644 src/com/wilko/jaim/.nbattrs create mode 100644 src/com/wilko/jaim/Buddy.java create mode 100644 src/com/wilko/jaim/BuddyUpdateTocResponse.java create mode 100644 src/com/wilko/jaim/ChatInviteTocResponse.java create mode 100644 src/com/wilko/jaim/ConfigTocResponse.java create mode 100644 src/com/wilko/jaim/ConnectionLostTocResponse.java create mode 100644 src/com/wilko/jaim/ErrorTocResponse.java create mode 100644 src/com/wilko/jaim/EvilTocResponse.java create mode 100644 src/com/wilko/jaim/FLAPDataFrame.java create mode 100644 src/com/wilko/jaim/FLAPErrorFrame.java create mode 100644 src/com/wilko/jaim/FLAPFrame.java create mode 100644 src/com/wilko/jaim/FLAPFrameException.java create mode 100644 src/com/wilko/jaim/FLAPFrameFactory.java create mode 100644 src/com/wilko/jaim/FLAPInputFrame.java create mode 100644 src/com/wilko/jaim/FLAPKeepAliveFrame.java create mode 100644 src/com/wilko/jaim/FLAPSignoffFrame.java create mode 100644 src/com/wilko/jaim/FLAPSignonFrame.java create mode 100644 src/com/wilko/jaim/GenericTocResponse.java create mode 100644 src/com/wilko/jaim/GotoTocResponse.java create mode 100644 src/com/wilko/jaim/Group.java create mode 100644 src/com/wilko/jaim/IMTocResponse.java create mode 100644 src/com/wilko/jaim/JaimConnection.java create mode 100644 src/com/wilko/jaim/JaimEvent.java create mode 100644 src/com/wilko/jaim/JaimEventListener.java create mode 100644 src/com/wilko/jaim/JaimException.java create mode 100644 src/com/wilko/jaim/JaimStateException.java create mode 100644 src/com/wilko/jaim/JaimTimeoutException.java create mode 100644 src/com/wilko/jaim/LoginCompleteTocResponse.java create mode 100644 src/com/wilko/jaim/NickTocResponse.java create mode 100644 src/com/wilko/jaim/SignOnTocResponse.java create mode 100644 src/com/wilko/jaim/TocAddBuddyCommand.java create mode 100644 src/com/wilko/jaim/TocAddDenyCommand.java create mode 100644 src/com/wilko/jaim/TocAddPermitCommand.java create mode 100644 src/com/wilko/jaim/TocChatJoinCommand.java create mode 100644 src/com/wilko/jaim/TocCommand.java create mode 100644 src/com/wilko/jaim/TocErrorDescriptions.properties create mode 100644 src/com/wilko/jaim/TocEvilCommand.java create mode 100644 src/com/wilko/jaim/TocGetInfoCommand.java create mode 100644 src/com/wilko/jaim/TocIMCommand.java create mode 100644 src/com/wilko/jaim/TocInitDoneCommand.java create mode 100644 src/com/wilko/jaim/TocResponse.java create mode 100644 src/com/wilko/jaim/TocResponseFactory.java create mode 100644 src/com/wilko/jaim/TocResponseHandler.java create mode 100644 src/com/wilko/jaim/TocSetAwayCommand.java create mode 100644 src/com/wilko/jaim/TocSetConfigCommand.java create mode 100644 src/com/wilko/jaim/TocSetIdleCommand.java create mode 100644 src/com/wilko/jaim/TocSetInfoCommand.java create mode 100644 src/com/wilko/jaim/TocSignonCommand.java create mode 100644 src/com/wilko/jaim/Utils.java create mode 100644 src/com/wilko/jaimtest/.nbattrs create mode 100644 src/com/wilko/jaimtest/JaimTest.java diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..e1178be --- /dev/null +++ b/.github/README.md @@ -0,0 +1,24 @@ +# Jaim + +This is a fork of [Jaim](https://jaimlib.sourceforge.net/), a Java library that implements the AOL TOC protocol. + +This fork features various improvements on the original Jaim: +- Support for chat invites + +## Original README +``` +Readme.txt for Jaimlib +---------------------- + +For an example of how to use Jaimlib see src/com/wilko/jaimtest/JaimTest.java + +You can run the example using: + +java -jar lib/jaimtest.jar + +Use ctrl-c to end the test + +For more information see http://jaimlib.sourceforge.net + +wilko@users.sourceforge.net +``` \ No newline at end of file diff --git a/.github/changes.txt b/.github/changes.txt new file mode 100644 index 0000000..37f5456 --- /dev/null +++ b/.github/changes.txt @@ -0,0 +1,32 @@ +Version 0.5 - 27/04/2002 +======================== +Added keepalive sending & timeout detection. This vastly improves connection +stability. +Added additional methods for buddy groups based on patch from Jon Madison + +Version 0.4 - 11/02/2002 +======================== +Added support for retrieving config from the server +Added support for storing config on the server +JaimConnection now supports multiple event listeners +Added support for Permit lists +Added getErrorDescription implementation to ErrorTocResponse +Fixed an error in the parsing of Error TOC responses +Added LoginComplete and ConnectionLost Toc responses +Event notification to listeners is now asynchronous to the main JaimConnection +thread + +Version 0.3 - 15/07/2002 +======================== +Turned off debugging messages by default +Changed behaviour of addBuddy - it now works after signon (Thanks James) +Changed behaviour of login - it now throws an exception if login fails + +Version 0.2 - 31/05/2002 +======================== +Added send rate limiting to sendIM() +Fixed a bug in the normalise function (Thanks Akom) + +Version 0.1 - 08/05/2002 +======================== +Initial release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..51181d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +build +lib +out +.DS_Store \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..1e41706 --- /dev/null +++ b/build.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
jaimlib.sourceforge.net]]>
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/doc/toc.txt b/doc/toc.txt new file mode 100644 index 0000000..5641f68 --- /dev/null +++ b/doc/toc.txt @@ -0,0 +1,489 @@ +# Copyright (c) 1998-9 America Online, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Version: TOC1.0 + +This document describes the protocol between TOC and TOC clients. +The protocol is built on TCP. Framing is done by SFLAP, +described at the bottom of this document. Inside each +SFLAP frame is a TOC command. + +The TOC protocol is ASCII based, and special attention +must be placed argument separation. The separator and +the rules of separation are different for messages inbound +to TOC and outbound to the client. The rules of separation +are described in sections below. + +The TOC server is built mainly to service the TIC and TiK clients. Since +the TIC client is a Java applet, and downloadable, TOC will NOT support +multiple TOC protocol versions at the same time. Therefore, TiK +users will be forced to upgrade if the protocol version changes. +TOC sends down the protocol version it expects the client +to speak and understand. Note, the protocol version is a string. + +Important Notes +=============== +* TOC will drop the connection if a command exceeds the maximum + length, which is currently 2048 bytes. So the client needs to + spend special attention to im, chat, and config message lengths. + There is an 8k length maximum from TOC to the client. + +* No commands should be sent to TOC (besides toc_signon) before + a SIGN_ON is received. If you do send a command before SIGN_ON + the command will be ignored, and in some case the connection + will be dropped. + +* Initial permit/deny items should be sent after receiving SIGN_ON + but before sending toc_init_done, otherwise the user will flash + on peoples buddylist who the user has denied. You will probably + want to send the toc_add_buddies at this time also. + +* After TOC sends the PAUSE message to a client, all messages sent + to TOC will be ignored, and in some cases the connection will + be dropped. Another SIGN_ON message will be sent to the client + when it is online again. The buddy list and permit/deny items must + be sent again, followed by the toc_init_done. In most cases the + SIGN_ON message will be sent between 1-2 seconds after the + PAUSE message. Therefore a client could choose to ignore the + PAUSE message and hope nothing bad happens. + + +Client -> TOC +============== +The commands and the arguments are usually separated by whitespaces. Arguments +with whitespace characters should be enclosed in quotes. Dollar signs, +curly brackets, square brackets, parentheses, quotes, and backslashes +must all be backslashed whether in quotes or not. It is usually +a good idea just to use quotes no matter what. All user names from clients +to TOC should be normalized (spaces removed and lowercased), and therefore +are the one exception to the always use quotes rule. + +When sending commands to the server you will not get a response +back confirming that the command format was correct or not! However +in some cases if the command format was incorrect the connection +will be dropped. + + +RoastingString="Tic/Toc" + +toc_signon + + The password needs to be roasted with the Roasting String if + coming over a FLAP connection, CP connections don't use + roasted passwords. The language specified will be used + when generating web pages, such as the get info pages. + Currently the only supported language is "english". + If the language sent isn't found, the default "english" + language will be used. The version string will be used + for the client identity, and must be less then 50 + characters. + + Passwords are roasted when sent to the host. This is done so they + aren't sent in "clear text" over the wire, although they are still + trivial to decode. Roasting is performed by first xoring each byte + in the password with the equivalent modulo byte in the roasting + string. The result is then converted to ascii hex, and prepended + with "0x". So for example the password "password" roasts to + "0x2408105c23001130" + +toc_init_done + Tells TOC that we are ready to go online. TOC clients should first + send TOC the buddy list and any permit/deny lists. However toc_init_done + must be called within 30 seconds after toc_signon, or the connection + will be dropped. Remember, it can't be called until after the SIGN_ON + message is received. Calling this before or multiple times after a + SIGN_ON will cause the connection to be dropped. + +toc_send_im [auto] + Send a message to a remote user. Remember to quote and encode the + message. If the optional string "auto" is the last argument, then the + auto response flag will be turned on for the im. + +toc_add_buddy [ [ [...]]] + Add buddies to your buddy list. This does not change your + saved config. + +toc_remove_buddy [ [ [...]]] + Remove buddies from your buddy list. This does not change your + saved config. + +toc_set_config + Set the config information for this user. The config information + is line oriented with the first character being the item type, + followed by a space, with the rest of the line being the item + value. Only letters, numbers, and spaces should be used. Remember + you will have to enclose the entire config in quotes. + + Item Types: + g - Buddy Group (All Buddies until the next g or the end of config + are in this group.) + b - A Buddy + p - Person on permit list + d - Person on deny list + m - Permit/Deny Mode. Possible values are + 1 - Permit All + 2 - Deny All + 3 - Permit Some + 4 - Deny Some + +toc_evil + Evil/Warn someone else. The 2nd argument is either the string + "norm" for a normal warning, or "anon" for an anonymous + warning. You can only evil people who have recently sent you + ims. The higher someones evil level, the slower they can + send message. + +toc_add_permit [ [ [...]]] + ADD the following people to your permit mode. If + you are in deny mode it will switch you to permit + mode first. With no arguments and in deny mode + this will switch you to permit none. If already + in permit mode, no arguments does nothing + and your permit list remains the same. + +toc_add_deny [ [ [...]]] + ADD the following people to your deny mode. If + you are in permit mode it will switch you to + deny mode first. With no arguments and in permit + mode, this will switch you to deny none. If + already in deny mode, no arguments does nothing + and your deny list remains unchanged. + +toc_chat_join + Join a chat room in the given exchange. Exchange is + an integer that represents a group of chat rooms. + Different exchanges have different properties. For + example some exchanges might have room replication (ie + a room never fills up, there are just multiple + instances.) and some exchanges might have navigational + information, and some exchanges might have ... Currently + exchange should always be 4, however this may + change in the future. You will either + receive an ERROR if the room couldn't be joined + or a CHAT_JOIN message. The Chat Room Name + is case insensitive and consecutive spaces + are removed. + +toc_chat_send + Send a message in a chat room using the chat room + id from CHAT_JOIN. Since reflection is always on in + TOC, you do not need to add the message to your chat UI, + since you will get a CHAT_IN with the message. + Remember to quote and encode the message. + +toc_chat_whisper + Send a message in a chat room using the chat room + id from CHAT_JOIN. This message is directed at + only one person. (Currently you DO need to add this to + your UI.) Remember to quote and encode the message. + Chat whispering is different from IMs since it is linked + to a chat room, and should usually be displayed in the chat + room UI. + +toc_chat_evil + Evil/Warn someone else inside a chat room. The 3rd argument is either + the string "norm" for a normal warning, or "anon" for an anonymous + warning. Currently chat evil is not turned on in the chat complex. + +toc_chat_invite [ [ [...]]] + Once you are inside a chat room you can invite other people into + that room. Remember to quote and encode the invite message. + +toc_chat_leave + Leave the chat room. + +toc_chat_accept + Accept a CHAT_INVITE message from TOC. The server will send a + CHAT_JOIN in response. + +toc_get_info + Gets a user's info a GOTO_URL or ERROR message will be sent back to the + client. + +toc_set_info + Set the LOCATE user information. This is basic HTML. + Remember to encode the info. + +toc_set_away [] + if the away message is present, then the unavailable + status flag is set for the user. If the away message + is not present, then the unavailable status flag is + unset. The away message is basic HTML, remember to + encode the information. + +toc_get_dir + Gets a user's dir info a GOTO_URL or ERROR message will be sent back to the + client. + +toc_set_dir + Set the DIR user information. This is a colon separated fields as in: + "first name":"middle name":"last name":"maiden name":"city":"state":"country":"email":"allow web searches" + Should return a DIR_STATUS msg. Having anything in the "allow web searches" + field allows people to use web-searches to find your directory info. + Otherwise, they'd have to use the client. + +toc_dir_search + Perform a search of the Oscar Directory, using colon separated fields as in: + "first name":"middle name":"last name":"maiden name":"city":"state":"country":"email" + Returns either a GOTO_URL or ERROR msg. + +toc_set_idle + Set idle information. If is 0 then the user isn't idle at all. + If is greater then 0 then the user has already been idle + for number of seconds. The server will automatically + keep incrementing this number, so do not repeatedly call with new + idle times. + +toc_set_caps [ [ [...]]] + Set my capabilities. All capabilities that we support need to + be sent at the same time. Capabilities are represented by + UUIDs. + +toc_rvous_propose - Not Implemented Yet + +toc_rvous_accept + Accept a rendezvous proposal from the user . + is the cookie from the RVOUS_PROPOSE + message. is the UUID the proposal was + for. contains a list of tlv tags followed by + base64 encoded values. + +toc_rvous_cancel + Cancel a rendezvous proposal from the user . + is the cookie from the RVOUS_PROPOSE + message. is the UUID the proposal was + for. contains a list of tlv tags followed by + base64 encoded values. + +toc_format_nickname + Reformat a user's nickname. An ADMIN_NICK_STATUS or ERROR message will + be sent back to the client. + +toc_change_passwd + Change a user's password. An ADMIN_PASSWD_STATUS or ERROR message will + be sent back to the client. + + +TOC -> Client +============== +All user names from TOC to client are NOT normalized, and are +sent as they should be displayed. String are NOT encoded, instead +we use colons as separators. So that you can have colons inside +of messages, everything after the colon before : should +be considered part of the message (ie don't just "split" on colons, +instead split with a max number of results.) + + +SIGN_ON: + This is sent after a successful toc_signon command is sent to TOC. + If the command was unsuccessful either the FLAP connection will + be dropped or you will receive a ERROR message. + +CONFIG: + A user's config. Config can be empty in which case the host was not able to + retrieve it, or a config didn't exist for the user. See toc_set_config + above for the format. + +NICK: + Tells you your correct nickname (ie how it should be capitalized and + spacing) + +IM_IN::: + Receive an IM from some one. Everything after the third colon is + the incoming message, including other colons. + +UPDATE_BUDDY:::::: + This one command handles arrival/depart/updates. Evil Amount is + a percentage, Signon Time is UNIX epoc, idle time is in minutes, UC (User Class) + is a two/three character string. + uc[0]: + ' ' - Ignore + 'A' - On AOL + uc[1] + ' ' - Ignore + 'A' - Oscar Admin + 'U' - Oscar Unconfirmed + 'O' - Oscar Normal + uc[2] + '\0' - Ignore + ' ' - Ignore + 'U' - The user has set their unavailable flag. + + + +ERROR::Var args + * General Errors * + 901 - $1 not currently available + 902 - Warning of $1 not currently available + 903 - A message has been dropped, you are exceeding + the server speed limit + + * Admin Errors * + 911 - Error validating input + 912 - Invalid account + 913 - Error encountered while processing request + 914 - Service unavailable + + * Chat Errors * + 950 - Chat in $1 is unavailable. + + * IM & Info Errors * + 960 - You are sending message too fast to $1 + 961 - You missed an im from $1 because it was too big. + 962 - You missed an im from $1 because it was sent too fast. + + * Dir Errors * + 970 - Failure + 971 - Too many matches + 972 - Need more qualifiers + 973 - Dir service temporarily unavailable + 974 - Email lookup restricted + 975 - Keyword Ignored + 976 - No Keywords + 977 - Language not supported + 978 - Country not supported + 979 - Failure unknown $1 + + * Auth errors * + 980 - Incorrect nickname or password. + 981 - The service is temporarily unavailable. + 982 - Your warning level is currently too high to sign on. + 983 - You have been connecting and + disconnecting too frequently. Wait 10 minutes and try again. + If you continue to try, you will need to wait even longer. + 989 - An unknown signon error has occurred $1 + + +EVILED:: + The user was just eviled. + +CHAT_JOIN:: + We were able to join this chat room. The Chat Room Id is + internal to TOC. + +CHAT_IN:::: + A chat message was sent in a chat room. + +CHAT_UPDATE_BUDDY::::... + This one command handles arrival/departs from a chat room. The + very first message of this type for each chat room contains the + users already in the room. + +CHAT_INVITE:::: + We are being invited to a chat room. + +CHAT_LEFT: + Tells tic connection to chat room has been dropped + +GOTO_URL:: + Goto a URL. Window Name is the suggested internal name of the window + to use. (Java supports this.) + +DIR_STATUS:: + is always 0 for success status. + +ADMIN_NICK_STATUS:: + is always 0 for success status. + +ADMIN_PASSWD_STATUS:: + is always 0 for success status. + + +PAUSE + Tells TIC to pause so we can do migration + +RVOUS_PROPOSE:::::::: + [:tlv tag1:tlv value1[:tlv tag2:tlv value2[:...]]] + Another user has proposed that we rendezvous with them to + perform the service specified by . They want us + to connect to them, we have their rendezvous ip, their + proposer_ip, and their verified_ip. The tlv values are + base64 encoded. + +Typical Signon Process +====================== +Except for the section marked optional this is an sequential +process. Each line MUST occur before the following line. + +* Client connects to TOC +* Client sends "FLAPON\r\n\r\n" +* TOC sends Client FLAP SIGNON +* Client sends TOC FLAP SIGNON +* Client sends TOC "toc_signon" message +* if login fails TOC drops client's connection + else TOC sends client SIGN_ON reply +* if Client doesn't support version it drops the connection + +[BEGIN OPTIONAL] + * TOC sends Client CONFIG + * Client sends TOC permit/deny stuff + * Client sends TOC toc_add_buddy message +[END OPTIONAL] + +* Client sends TOC toc_init_done message + + +SFLAP Documentation +=================== +SFLAP is pretty much a FLAP connection except the DATA frame payload is a null +terminated string when traveling from client to host, it is NOT null +terminated when traveling from host to client. The FLAP Header is binary +data, and is in network byte order. The data portion is at offset 6, after the +header. The sequence number is sequential in each direction. So +packets from the server to client have one sequence number, while +the packets from the client to server have an independent +increasing number. + +FLAP Header (6 bytes) +----------- +Offset Size Type +0 1 ASTERISK (literal ASCII '*') +1 1 Frame Type +2 2 Sequence Number +4 2 Data Length + + +Valid Frame Type Values +----------------------- +1 SIGNON +2 DATA +3 ERROR (Not used by TOC) +4 SIGNOFF (Not used by TOC) +5 KEEP_ALIVE + + +TOC SIGNON FRAME TYPE +--------------------- +Sequence Number contains the initial sequence number used in each direction. +Data Length contains the payload length, with the payload described +below. The payload area is NOT null terminated. + +Host To Client: + 4 byte FLAP version (1) + +Client To Host: + 4 byte FLAP version (1) + 2 byte TLV Tag (1) + 2 byte Normalized User Name Length + N byte Normalized User Name (NOT null terminated) + + +TOC DATA FRAME TYPE +------------------- +Sequence Number contains the next sequence number. +Data Length is the length of the payload, including the null termination +from client to host. + diff --git a/jaimlib.iml b/jaimlib.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/jaimlib.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/wilko/jaim/.nbattrs b/src/com/wilko/jaim/.nbattrs new file mode 100644 index 0000000..8117889 --- /dev/null +++ b/src/com/wilko/jaim/.nbattrs @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/wilko/jaim/Buddy.java b/src/com/wilko/jaim/Buddy.java new file mode 100644 index 0000000..486b7ce --- /dev/null +++ b/src/com/wilko/jaim/Buddy.java @@ -0,0 +1,88 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * Buddy.java + * + * Created on 4 May 2002, 12:05 + */ + +package com.wilko.jaim; + +/** This is a buddy object that holds the buddy's name and other + * information about a buddy. + * @author Brett Humphreys + */ + public class Buddy { + /** Name of the buddy */ + private String buddyName; + + /** Permit value */ + private boolean permit; + + /** deny value */ + private boolean deny; + + /** Constructor that sets the buddy name + * @param name the name of this buddy. + */ + public Buddy ( String name ) + { + buddyName = name; + } + + /** Gets the buddy name + * @return buddy name + */ + public String getName() + { + return buddyName; + } + /** Sets the permit value + * @param permitVal what to set permit to + */ + public void setPermit( boolean permitVal ) + { + permit = permitVal; + } + + /** Gets the permit value + * @return permit value + */ + public boolean getPermit( ) + { + return permit; + } + + /** Sets the deny value + * @param denyVal what to set deny to + */ + public void setDeny( boolean denyVal ) + { + deny = denyVal; + } + + /** Gets the deny value + * @return deny value + */ + public boolean getDeny( ) + { + return deny; + } + } diff --git a/src/com/wilko/jaim/BuddyUpdateTocResponse.java b/src/com/wilko/jaim/BuddyUpdateTocResponse.java new file mode 100644 index 0000000..b9de8db --- /dev/null +++ b/src/com/wilko/jaim/BuddyUpdateTocResponse.java @@ -0,0 +1,210 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * BuddyUpdateTocResponse.java + * + * Created on 5 May 2002, 21:19 + */ + +package com.wilko.jaim; + +import java.util.Date; +import java.util.StringTokenizer; + +/** A BuddyUpdateTocResponse is delivered to a {@link JaimEventListener } when a buddy update is received from the TOC server + * @author paulw + * @version $Revision: 1.7 $ + */ +public class BuddyUpdateTocResponse extends TocResponse implements TocResponseHandler { + + private String buddyName; + private boolean online; + private int evil; + private int idleTime; + private boolean onAOL; + private boolean unconfirmed; + private boolean admin; + private boolean confirmed; + private Date signonTime; + private boolean away; + + public static String RESPONSE_TYPE="UPDATE_BUDDY"; + + /** Creates new BuddyUpdateTocResponse */ + public BuddyUpdateTocResponse() { + buddyName=""; + online=false; + evil=0; + idleTime=0; + onAOL=false; + unconfirmed=false; + admin=false; + confirmed=false; + away=false; + } + + /** The parseString method is used to populate the fields of this class from a Buddy Update string from the TOC server + * @param str The String containing the buddy update + */ + public TocResponse parseString(java.lang.String str) { + BuddyUpdateTocResponse tr=new BuddyUpdateTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + cmd=str; + StringTokenizer st=new StringTokenizer(str,":"); + + st.nextToken(); + buddyName=st.nextToken(); + String onlineStr=st.nextToken(); + if (onlineStr.equals("T")) + { + online=true; + } + else + { + online=false; + } + + evil=Integer.parseInt(st.nextToken()); + long signon=Long.parseLong(st.nextToken()); + signonTime=new Date(signon*1000); + idleTime=Integer.parseInt(st.nextToken()); + String userclass=st.nextToken(); + if (userclass.charAt(0) == 'A') + onAOL=true; + if (userclass.charAt(1) == 'A') + { + admin=true; + } + else + { + if (userclass.charAt(1)=='U') + { + unconfirmed=true; + } + else + { + if(userclass.charAt(1)=='O') + { + confirmed=true; + } + } + } + if (userclass.length()>2) + { + if (userclass.charAt(2)=='U') + { + away=true; + } + } + } + + /** Get the away status of the buddy specified by this update + * @return true if the buddy is "away" + */ + public boolean isAway() + { + return(away); + } + + /** Get the response type of this response. This method is used by the response dispatcher within JaimConnection + * @return The response type + */ + public String getResponseType() { + return RESPONSE_TYPE; + } + + /** Obtain the buddy name from this update + * @return The buddy name + */ + public String getBuddy() + { + return(buddyName); + } + + /** Obtain the online status of this buddy update + * @return true if the buddy is on line + */ + public boolean isOnline() + { + return(online); + } + + /** Obtain the idle time of this buddy + * @return The idle time in seconds + */ + public int getIdleTime() + { + return(idleTime); + } + + /** Obtain the "Evil" (Warning) level of this buddy + * @return The warning level as a percentage + */ + public int getEvil() + { + return(evil); + } + + /** Is this buddy an "Administrator" + * @return true if an administrator + */ + public boolean isAdmin() + { + return(admin); + } + + /** IS this buddy a "confirmed" user + * @return True if this buddy is confirmed + */ + public boolean isConfirmed() + { + return(confirmed); + } + + /** Is this user an "Unconfirmed user" + * @return True if this user is unconfirmed + */ + public boolean isUnconfirmed() + { + return(unconfirmed); + } + + /** Get the signon time of this buddy + * @return The date/time of signon + */ + public Date getSignonTime() + { + return(signonTime); + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/ChatInviteTocResponse.java b/src/com/wilko/jaim/ChatInviteTocResponse.java new file mode 100644 index 0000000..3c4d894 --- /dev/null +++ b/src/com/wilko/jaim/ChatInviteTocResponse.java @@ -0,0 +1,103 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * BuddyUpdateTocResponse.java + * + * Created on 5 May 2002, 21:19 + */ + +package com.wilko.jaim; + +import java.util.Date; +import java.util.StringTokenizer; + +/** A BuddyUpdateTocResponse is delivered to a {@link JaimEventListener } when a buddy update is received from the TOC server + * @author paulw + * @version $Revision: 1.7 $ + */ +public class ChatInviteTocResponse extends TocResponse implements TocResponseHandler { + + private String roomName; + private String roomID; + private String senderScreenname; + private String message; + + public static String RESPONSE_TYPE="CHAT_INVITE"; + + /** Creates new BuddyUpdateTocResponse */ + public ChatInviteTocResponse() { + roomName = ""; + roomID = ""; + senderScreenname = ""; + message = ""; + } + + /** The parseString method is used to populate the fields of this class from a Buddy Update string from the TOC server + * @param str The String containing the buddy update + */ + public TocResponse parseString(String str) { + ChatInviteTocResponse tr = new ChatInviteTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + cmd=str; + StringTokenizer st=new StringTokenizer(str,":"); + + st.nextToken(); + roomName = st.nextToken(); + roomID = st.nextToken(); + senderScreenname = st.nextToken(); + message = st.nextToken(); + } + + /** Get the response type of this response. This method is used by the response dispatcher within JaimConnection + * @return The response type + */ + public String getResponseType() { + return RESPONSE_TYPE; + } + + public String getRoomName() { + return roomName; + } + public String getRoomID() { + return roomID; + } + + public String getSenderScreenname() { + return senderScreenname; + } + + public String getMessage() { + return message; + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/ConfigTocResponse.java b/src/com/wilko/jaim/ConfigTocResponse.java new file mode 100644 index 0000000..49bed69 --- /dev/null +++ b/src/com/wilko/jaim/ConfigTocResponse.java @@ -0,0 +1,194 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * ConfigTocResponse.java + * Created on 1, October 2002 + */ + package com.wilko.jaim; + + import java.util.*; + + /** A ConfigTocResponse contains the config message received from + * the toc server. + *This response is handled by the JaimConnection class, but may also be used by client programs. + *Once this event has been received, information returned from {@link JaimConnection#getGroups} is valid + * @author Brett Humphreys, Paul Wilkinson + */ + public class ConfigTocResponse extends TocResponse implements TocResponseHandler { + + public static String RESPONSE_TYPE="CONFIG"; + + /** The Vector of Group objects */ + private Vector buddyList = new Vector(); + + /** The HashMap of known buddies */ + private HashMap buddies; + + /** The mode for this configuration */ + private int mode; + + /** Value for mode that indicates PERMIT ALL mode */ + public static final int PERMIT_ALL=1; + + /** Value for mode that indicates DENY ALL mode */ + public static final int DENY_ALL=2; + + /** Value for mode that indicates PERMIT SOME mode */ + public static final int PERMIT_SOME=3; + + /** Value for mode that indicates DENY SOME mode */ + public static final int DENY_SOME=4; + + /** Returns an Enumeration of groups. Each Entry is a {@link Group} + * Each group then has an Enumeration of buddies within that group See {@link Group#enumerateBuddies}. + * @return list of Group elements or an empty list if none are found. + */ + public Enumeration enumerateGroups() + { + return buddyList.elements(); + } + + /** Returns a Collection of groups. Each element is a {@link Group) + * @return the groups + */ + public Collection getGroups() { + java.util.Collection result = new Vector(buddyList); + return result; + } + + + /** Get the response type of this response. This method is used by the response dispatcher within JaimConnection + * @return The response type + */ + public String getResponseType() { + return RESPONSE_TYPE; + } + /** Parses the config string. + */ + public TocResponse parseString(String message) + { + ConfigTocResponse tr = new ConfigTocResponse(); + tr.doParse(message); + return(tr); + } + + private void doParse(String message) + { + cmd=message; + int colonIndex = message.indexOf(':'); + //throw away the first word. + message = message.substring(colonIndex+1, message.length()); + buddies = new HashMap(); + StringTokenizer tok = new StringTokenizer(message,"\n"); + String itemType; + String itemValue; + Group currentGroup=null; + Buddy tmpBuddy; + while( tok.hasMoreTokens() ) + { + // Can't tokenize on both \n and space since there could be spaces + // in the name, so parsing by hand. + itemType = tok.nextToken(); + int firstSpace = itemType.indexOf(' '); + itemValue = itemType.substring(firstSpace+1, itemType.length()); + itemType = itemType.substring(0, firstSpace); + + char type = itemType.charAt(0); + switch (type) + { + case 'g': + currentGroup = new Group(itemValue); + buddyList.add(currentGroup); + break; + + case 'b': + + tmpBuddy = getBuddy(itemValue); + //this shouldn't happen, but: + if(currentGroup==null) + { + currentGroup = new Group(""); + buddyList.add(currentGroup); + } + currentGroup.addBuddy(tmpBuddy); + + + break; + + case 'p': + tmpBuddy = getBuddy(itemValue); + tmpBuddy.setPermit(true); + break; + + case 'm': + setMode(Integer.valueOf(itemValue).intValue()); + break; + + case 'd': + + tmpBuddy = getBuddy(itemValue); + tmpBuddy.setDeny(true); + break; + } + } + } + + /** Return an existing Buddy with the specified name or return a new buddy if the name is not known + * The buddy is added to the buddies hash if it is a new buddy + * @param The name of the buddy we are looking for + * @return The buddy object + */ + + private Buddy getBuddy(String buddyName) + { + Buddy retBuddy = (Buddy)buddies.get(buddyName); + if (retBuddy== null) + { + retBuddy=new Buddy(buddyName); + buddies.put(buddyName,retBuddy); + } + return(retBuddy); + } + + /** Sets the mode for this configuration + * @param modeVal the string value of the mode (1-4) + */ + public void setMode( int modeVal ) + { + mode = modeVal; + } + + /** Gets the mode for this configuration + * @return mode for the configuration + */ + public int getMode( ) + { + return mode; + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + + } diff --git a/src/com/wilko/jaim/ConnectionLostTocResponse.java b/src/com/wilko/jaim/ConnectionLostTocResponse.java new file mode 100644 index 0000000..a01b642 --- /dev/null +++ b/src/com/wilko/jaim/ConnectionLostTocResponse.java @@ -0,0 +1,50 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * ConnectionLostTocResponse.java + * + * Created on November 2, 2002, 2:52 PM + */ + +package com.wilko.jaim; + +/** + * This is a "pseudo" TOC response - it is delivered to JaimLib clients to indicate that the connection to the server has been lost. + * @author wilko + * @version: $revision: $ + */ +public class ConnectionLostTocResponse extends TocResponse { + + public static final String RESPONSE_TYPE="CONNECTIONLOST"; + + /** Creates a new instance of LoginCompleteTocResponse */ + public ConnectionLostTocResponse() { + } + + public String getResponseType() { + return (RESPONSE_TYPE); + } + + public String toString() + { + return (RESPONSE_TYPE); + } + +} diff --git a/src/com/wilko/jaim/ErrorTocResponse.java b/src/com/wilko/jaim/ErrorTocResponse.java new file mode 100644 index 0000000..abf09b6 --- /dev/null +++ b/src/com/wilko/jaim/ErrorTocResponse.java @@ -0,0 +1,145 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * ErrorTocResponse.java + * + * Created on 4 May 2002, 14:52 + */ + +package com.wilko.jaim; + +import java.util.MissingResourceException; + +/** This TOC response is sent to a {@link JaimEventListener } when an error message is received from the TOC server + * + * @author paulw + * @version $Revision: 1.7 $ + */ +public class ErrorTocResponse extends TocResponse implements TocResponseHandler { + + int errorCode; + String errorText; + + public static final String RESPONSE_TYPE="ERROR"; + + /** Creates new ErrorTocResponse */ + public ErrorTocResponse() { + errorCode=0; + errorText=""; + } + + + /** Parse the error response string sent by the TOC server + * @param str The error response string + */ + public TocResponse parseString(String str) + { + ErrorTocResponse tr=new ErrorTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + + cmd=str; + int colonPos=str.indexOf(':'); + if (colonPos!=-1) + { + str=str.substring(colonPos+1); + colonPos=str.indexOf(':'); + if (colonPos!=-1) + { + errorCode=Integer.parseInt(str.substring(0,colonPos)); + errorText=str.substring(colonPos+1); + } + else + { + errorCode=Integer.parseInt(str); + } + } + + } + + /** Obtain the error code for this response + * @return The error code + */ + public int getErrorCode() + { + return(errorCode); + } + + /** Get the error text (if any) associated with this error response + * @return The error text + */ + public String getErrorText() + { + return(errorText); + } + + + /** Obtain the error message that corresponds to this error. + * @return The error text with any applicable error argument text inserted + */ + public String getErrorDescription() { + try { + StringBuffer desc=new StringBuffer(java.util.ResourceBundle.getBundle("com/wilko/jaim/TocErrorDescriptions").getString(Integer.toString(errorCode))); + String sDesc=desc.toString(); + int argpos=sDesc.indexOf("%s"); + if (argpos != -1) { + desc.replace(argpos,argpos+1,errorText); + } + return(desc.toString()); + + } + catch (MissingResourceException e) { + return("Unable to locate error description:"+e.toString()); + } + } + + /** Obtain the error message that corresponds to the specified error code + * @param code The error code + * @return The error text + */ + static public String getErrorDescription(int code) + { + try + { + return(java.util.ResourceBundle.getBundle("com/wilko/jaim/TocErrorDescriptions").getString(Integer.toString(code))); + } + catch (MissingResourceException e) + { + return("Unable to locate error description:"+e.toString()); + } + } + + public String getResponseType() { + return RESPONSE_TYPE; + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/EvilTocResponse.java b/src/com/wilko/jaim/EvilTocResponse.java new file mode 100644 index 0000000..475523c --- /dev/null +++ b/src/com/wilko/jaim/EvilTocResponse.java @@ -0,0 +1,117 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * EvilTocResponse.java + * + * Created on 6 May 2002, 16:49 + */ + +package com.wilko.jaim; + +import java.util.StringTokenizer; + +/** An EvilTocResponse is delivered to a {@link JaimEventListener } when the signed on buddy is "eviled" or warned + * @author paulw + * @version $Revision: 1.6 $ + */ +public class EvilTocResponse extends TocResponse implements TocResponseHandler { + + private boolean anonymousEvil; + private int evilAmount; + private String evilBy; + + public static final String RESPONSE_TYPE="EVILED"; + + /** Creates new EvilTocResponse */ + public EvilTocResponse() { + anonymousEvil=true; + evilBy=""; + evilAmount=0; + } + + /** Parse the evil message from the TOC server + * @param str The evil message + */ + public TocResponse parseString(java.lang.String str) { + EvilTocResponse tr=new EvilTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + + StringTokenizer st=new StringTokenizer(str,":"); + + st.nextToken(); // skip over "EVILED" + evilAmount=Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + { + evilBy=st.nextToken(); + anonymousEvil=false; + } + else + { + anonymousEvil=true; + } + } + + /** Get the evil amount from this response. This is the current evil or warning level for the authenticated buddy, not the increment specified by the last warning + * @return The cumulative evil or warning level + */ + public int getEvilAmount() + { + return(evilAmount); + } + + /** Obtain the name of the buddy that issued the warning. + * @return The buddy name that issued the warning + * @see #isAnonymous + */ + public String getEvilBy() + { + return(evilBy); + } + + /** Obtain the anonymous status of this warning + * @return true if this warning was issued anonymously + */ + public boolean isAnonymous() + { + return(anonymousEvil); + } + + /** Used by the response dispatcher + * @return The response type + */ + public String getResponseType() { + return RESPONSE_TYPE; + } + + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/FLAPDataFrame.java b/src/com/wilko/jaim/FLAPDataFrame.java new file mode 100644 index 0000000..41a538c --- /dev/null +++ b/src/com/wilko/jaim/FLAPDataFrame.java @@ -0,0 +1,76 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FlapDataFrame.java + * + * Created on 3 May 2002, 14:54 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public class FLAPDataFrame extends FLAPFrame { + + private int frameLen; + + /** Creates new FlapDataFrame */ + public FLAPDataFrame() { + frame[1]=FLAP_FRAME_DATA; + frameLen=1; + frame[FLAP_DATA_OFFSET]=0; + } + + public FLAPDataFrame(byte frameData[]) + { + frame[1]=FLAP_FRAME_DATA; + frameLen=1; + frame[FLAP_DATA_OFFSET]=0; + setFrameData(frameData); + } + + + public int getFLAPFrameType() { + return(FLAPFrame.FLAP_FRAME_DATA); + } + + public void addString(String s) + { + frameLen--; // Backspace over '0' + for (int i=0;iFLAPFrameException without detail message. + */ + public FLAPFrameException() { + } + + + /** + * Constructs an FLAPFrameException with the specified detail message. + * @param msg the detail message. + */ + public FLAPFrameException(String msg) { + super(msg); + } +} + + diff --git a/src/com/wilko/jaim/FLAPFrameFactory.java b/src/com/wilko/jaim/FLAPFrameFactory.java new file mode 100644 index 0000000..475f1d5 --- /dev/null +++ b/src/com/wilko/jaim/FLAPFrameFactory.java @@ -0,0 +1,69 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FLAPFrameFactory.java + * + * Created on 3 May 2002, 15:04 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public abstract class FLAPFrameFactory { + + /** Creates new FLAPFrameFactory */ + public FLAPFrameFactory() { + } + + public static FLAPFrame createFLAPFrame(byte[] frameData) throws FLAPFrameException { + FLAPFrame f=null; + if (frameData[0]!='*') + { + throw new FLAPFrameException("Frame does not start with '*'"); + } + + switch (frameData[1]) + { + case FLAPFrame.FLAP_FRAME_SIGNON: + f=new FLAPSignonFrame(frameData); + break; + case FLAPFrame.FLAP_FRAME_DATA: + f=new FLAPDataFrame(frameData); + break; + case FLAPFrame.FLAP_FRAME_ERROR: + f=new FLAPErrorFrame(frameData); + break; + case FLAPFrame.FLAP_FRAME_SIGNOFF: + f=new FLAPSignoffFrame(frameData); + break; + case FLAPFrame.FLAP_FRAME_KEEP_ALIVE: + f=new FLAPKeepAliveFrame(frameData); + break; + default: + throw new FLAPFrameException("Illegal FLAP Frame type: "+Integer.toString(frameData[1])); + } + return(f); + } + +} diff --git a/src/com/wilko/jaim/FLAPInputFrame.java b/src/com/wilko/jaim/FLAPInputFrame.java new file mode 100644 index 0000000..bdceb3c --- /dev/null +++ b/src/com/wilko/jaim/FLAPInputFrame.java @@ -0,0 +1,76 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FLAPInputFrame.java + * + * Created on 3 May 2002, 15:52 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public class FLAPInputFrame extends FLAPFrame { + + /** Creates new FLAPInputFrame */ + private int frameLen; + + public FLAPInputFrame() { + frameLen=0; + super.initialise(); + } + + public void addFrameData(byte b) + { + frame[frameLen++]=b; + } + + public byte[] getFrameData() + { + byte[] b=new byte[frameLen]; + System.arraycopy(frame,0,b,0,frameLen); + return(b); + } + + public void resetInputFrame() + { + frameLen=0; + } + + public boolean completeFrameRead() + { + if (frameLen > 5) + { + if (frameLen-6 == getLength()) + { + return(true); + } + } + return(false); + } + + public int getFLAPFrameType() { + return(-1); + } + +} diff --git a/src/com/wilko/jaim/FLAPKeepAliveFrame.java b/src/com/wilko/jaim/FLAPKeepAliveFrame.java new file mode 100644 index 0000000..561c53e --- /dev/null +++ b/src/com/wilko/jaim/FLAPKeepAliveFrame.java @@ -0,0 +1,56 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FLAPKeepAliveFrame.java + * + * Created on 3 May 2002, 14:54 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.4 $ + */ +public class FLAPKeepAliveFrame extends FLAPFrame { + + /** Creates new FLAPKeepAliveFrame */ + public FLAPKeepAliveFrame() { + this.initialise(); + } + + public FLAPKeepAliveFrame(byte frameData[]) + { + initialise(); + setFrameData(frameData); + } + + protected void initialise() + { + super.initialise(); + frame[1]=FLAP_FRAME_KEEP_ALIVE; + } + + public int getFLAPFrameType() { + return (FLAPFrame.FLAP_FRAME_KEEP_ALIVE); + } + +} diff --git a/src/com/wilko/jaim/FLAPSignoffFrame.java b/src/com/wilko/jaim/FLAPSignoffFrame.java new file mode 100644 index 0000000..11c93af --- /dev/null +++ b/src/com/wilko/jaim/FLAPSignoffFrame.java @@ -0,0 +1,52 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FLAPSignoffFrame.java + * + * Created on 3 May 2002, 14:54 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public class FLAPSignoffFrame extends FLAPFrame { + + /** Creates new FlapSignonFrame */ + public FLAPSignoffFrame() { + + frame[1]=FLAP_FRAME_SIGNOFF; + } + + public FLAPSignoffFrame(byte frameData[]) + { + frame[1]=FLAP_FRAME_SIGNOFF; + setFrameData(frameData); + } + + + public int getFLAPFrameType() { + return(FLAPFrame.FLAP_FRAME_SIGNOFF); + } + +} diff --git a/src/com/wilko/jaim/FLAPSignonFrame.java b/src/com/wilko/jaim/FLAPSignonFrame.java new file mode 100644 index 0000000..93ef5ed --- /dev/null +++ b/src/com/wilko/jaim/FLAPSignonFrame.java @@ -0,0 +1,90 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * FlapSignonFrame.java + * + * Created on 3 May 2002, 14:54 + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public class FLAPSignonFrame extends FLAPFrame { + + /** Creates new FlapSignonFrame */ + public FLAPSignonFrame() { + frame[1]=FLAP_FRAME_SIGNON; + } + + public FLAPSignonFrame(byte frameData[]) + { + frame[1]=FLAP_FRAME_SIGNON; + setFrameData(frameData); + } + + public int getFLAPVersion() + { + return(((frame[6]&0xff)*16777216)+((frame[7]&0xff)*65536)+((frame[8]&0xff)*256)+(frame[9]&0xff)); + } + + public void setFLAPVersion(int version) + { + for (int i=3;i>=0;i--) + { + frame[6+i]=(byte)(version&0xff); + version=version>>8; + } + } + + public void setTLVTag(int tag) + { + for (int i=1;i>=0;i--) + { + frame[10+i]=(byte)(tag&0xff); + tag=tag>>8; + } + } + + public void setUserName(String name) + { + + int len=0; + for (int i=0;i buddies.size()) { + buddies.add(buddy); + } + else { + buddies.add(pos,buddy); + } + } + + /** This method gets the group name + * @return the group name + */ + public String getName() { + return groupName; + } + + /** This method returns the buddies in this group + * @return an Enumeration of {@link Buddy} objects + */ + public Enumeration enumerateBuddies() { + return buddies.elements(); + } + + /** This method returns the number of buddies in this group + * @return buddy count + */ + public int getBuddyCount() { + return(buddies.size()); + } + + /** This method returns the buddies in this group + * @return a Collection of {@link Buddy} objects + */ + public java.util.Collection getBuddies() { + java.util.Collection cReturn = new java.util.Vector(buddies); + return cReturn; + } + +} diff --git a/src/com/wilko/jaim/IMTocResponse.java b/src/com/wilko/jaim/IMTocResponse.java new file mode 100644 index 0000000..ff10804 --- /dev/null +++ b/src/com/wilko/jaim/IMTocResponse.java @@ -0,0 +1,122 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * TocIMResponse.java + * + * Created on 4 May 2002, 14:38 + */ + +package com.wilko.jaim; + +/** This response is delivered to a {@link JaimEventListener } when an instant message is received + * @author paulw + * @version $Revision: 1.6 $ + */ +public class IMTocResponse extends TocResponse implements TocResponseHandler { + + String from; + boolean autoResponse; + String msg; + + public static final String RESPONSE_TYPE="IM_IN"; + + /** Creates new TocIMResponse */ + public IMTocResponse() { + from=""; + msg=""; + autoResponse=false; + } + + /** Obtain the name of the buddy who sent this instant message + * @return The senders name + */ + public String getFrom() + { + return(from); + } + + /** Obtain the message + * @return The message + * @see Utils#stripHTML + */ + public String getMsg() + { + return(msg); + } + + /** Is this response an automatically generated response? + * @return true if this is an automatically generated response + */ + public boolean getAutoResponse() + { + return(autoResponse); + } + + /** Parse an incoming IM response string + * @param str The string to be parsed + */ + public TocResponse parseString(java.lang.String str) { + IMTocResponse tr=new IMTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + cmd=str; + int colonPos=str.indexOf(':'); + if (colonPos!=-1) + { + str=str.substring(colonPos+1); + colonPos=str.indexOf(':'); + if (colonPos != -1) + { + from=str.substring(0,colonPos); + str=str.substring(colonPos+1); + colonPos=str.indexOf(':'); + if (str.charAt(0) == 'T') + { + autoResponse=true; + } + if (colonPos != -1) + { + msg=str.substring(colonPos+1); + } + } + } + + } + + /** Obtain the response type for response dispatching purposes + * @return The response type + */ + public String getResponseType() { + return(RESPONSE_TYPE); + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return (Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/JaimConnection.java b/src/com/wilko/jaim/JaimConnection.java new file mode 100644 index 0000000..7fbd133 --- /dev/null +++ b/src/com/wilko/jaim/JaimConnection.java @@ -0,0 +1,926 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * JaimConnection.java + * + * Created on 4 May 2002, 08:38 + */ + +package com.wilko.jaim; + +import java.net.*; +import java.text.DateFormat; +import java.io.*; +import java.util.*; + +/** The JaimConnection object is the primary interface into the Jaim library. + * Programs should instantiate a JaimConnection (in most cases the simple constructor should be used). + * Once JaimConnection has been instantiated, call {@link #connect} followed by {@link #logIn}. + * + * + * @author paulw + * @version $Revision: 1.20 $ + */ +public class JaimConnection implements java.lang.Runnable { + + private Socket s; + private InputStream sin; + private OutputStream sout; + private boolean connected; + private boolean loggedIn; + private boolean loginComplete; + private boolean configValid; + private String host; + private int port; + private int clientSequence; + private int serverSequence; + private ReceiverThread rt; + private DeliveryThread dt; + private Vector eventListeners; + private HashMap watchedBuddies; + private HashMap buddies; + private HashMap groups; + private String nickName; + private long lastMessageSendTime; + private boolean debug; + private Thread myThread; + private Vector messageQueue; + private boolean exit; + private long lastKeepAlive; + + // Number of send "points" - used to control send rate + private int sendPoints=10; + + + private static final int MAX_POINTS=10; + private static final int BLOCK_POINTS=5; + private static final int POINT_RECOVERY_TIME=2200; // Recover one point every 2.2 seconds + private static final int THRESHOLD_DELAY=5000; // Delay when we are threshold of being blocked + + private static final int WAIT_TIME=61000; // Wait 61 secs for a keep alive + + /** Creates new JaimConnection that connects to the default host and port. + * In most cases this constructor should be used. + */ + public JaimConnection() { + host="toc.oscar.aol.com"; + port=9898; + startMe(); + + } + + /** Creates a new Jaim Connection to the specified host/port. + * There are currently no reasons to call this constructor, however AOL may change the TOC host and port in the future + * @param host The hostname or IP address of the TOC server + * @param port The port number to connect to on the host + */ + public JaimConnection(String host,int port) { + this.host=host; + this.port=port; + startMe(); + } + + /** start the message dispatcher thread + */ + + private void startMe() { + connected=false; + loggedIn=false; + eventListeners=new Vector(); + loginComplete=false; + lastMessageSendTime=0; + watchedBuddies=new HashMap(); + buddies=new HashMap(); + groups=new HashMap(); + debug=false; + exit=false; + rt=null; + configValid=false; + lastKeepAlive=System.currentTimeMillis(); + TocResponseFactory.addResponseHandler(new BuddyUpdateTocResponse()); + TocResponseFactory.addResponseHandler(new ErrorTocResponse()); + TocResponseFactory.addResponseHandler(new EvilTocResponse()); + TocResponseFactory.addResponseHandler(new IMTocResponse()); + TocResponseFactory.addResponseHandler(new SignOnTocResponse()); + TocResponseFactory.addResponseHandler(new NickTocResponse()); + TocResponseFactory.addResponseHandler(new GotoTocResponse()); + TocResponseFactory.addResponseHandler(new ConfigTocResponse()); + TocResponseFactory.addResponseHandler(new ChatInviteTocResponse()); + messageQueue=new Vector(); + myThread = new Thread(this); + myThread.setDaemon(true); + myThread.start(); + dt=new DeliveryThread(); + dt.setDaemon(true); + dt.start(); + } + + + + /** Enable/Disable debugging messages to stdout + * @param debug true if debugging messages should be output + */ + + public void setDebug(boolean debug) { + this.debug=debug; + } + + + /** Specify the intermessage delay time.
+ * The {@link #sendIM } method will ensure that at least this amount of time has elapsed between messages + * @param msec The delay period in milliseconds + * @deprecated This function is no longer used - send throttling is automatic + */ + public void setInterMessageDelay(long msec) { + + } + + /** Get the intermessage delay time + * @return The intermessage delay time in milliseconds + * @deprecated This function is no longer used + */ + public long getInterMessageDelay() { + return(0); + } + + /** Set the EventListener object. This object will be notified of incoming TOC events + * @param l The listener class to be notified + * @deprecated replaced by {@link #addEventListener} + */ + public void setEventListener(JaimEventListener l) throws TooManyListenersException { + eventListeners.add(l); + } + + /** Add an EventListener object. This object will be notified of incoming TOC events + * @param l The listener class to be notified + */ + + public void addEventListener(JaimEventListener l) { + eventListeners.add(l); + } + + /** Remove an EventListener object. This object will no longer be notified of incoming TOC events + * @param l The listener class to be removed + */ + + public void removeEventListener(JaimEventListener l) { + eventListeners.remove(l); + } + + + /** Initiate a connection to the TOC server + * @throws IOException If an underlying network communication fails + */ + public void connect() throws IOException { + s=new Socket(host,port); + s.setSoTimeout(500); + sin=s.getInputStream(); + sout=s.getOutputStream(); + + sout.write("FLAPON\r\n\r\n".getBytes()); + + FLAPInputFrame inFrame = new FLAPInputFrame(); + + int i=-1; + + + while (!inFrame.completeFrameRead()) { + i=sin.read(); + inFrame.addFrameData((byte)i); + } + + try { + FLAPFrame f = FLAPFrameFactory.createFLAPFrame(inFrame.getFrameData()); + FLAPSignonFrame sf = (FLAPSignonFrame)f; + if (debug) { + System.out.println("Starting sequence="+sf.getSequence()); + System.out.println("FLAP version = "+sf.getFLAPVersion()); + } + clientSequence=sf.getSequence(); + serverSequence=sf.getSequence(); + } + catch (FLAPFrameException e) { + throw new IOException("FLAPFrameException:"+e.toString()); + } + if (rt!=null) { + rt.pleaseExit(); + } + rt=new ReceiverThread(this); + rt.setInputStream(sin); + rt.setDaemon(true); + rt.start(); + connected=true; + } + + /** Disconnect from the TOC server + * @throws IOException if a network transport error occurs + */ + public void disconnect() throws IOException { + exit=true; + rt.pleaseExit(); + try { + rt.join(700); + myThread.join(700); + } + catch (InterruptedException e) { + } + + if (connected) { + if (loggedIn) { + logOut(); + } + s.close(); + connected=false; + } + } + + + /** Check if the TOC login process has completed + * @return true if the login process is complete + */ + public boolean isLoginComplete() { + return(loginComplete); + } + + /** Log out from the TOC server + */ + public void logOut() { + loggedIn=false; + loginComplete=false; + configValid=false; + + } + + /** Get the formatted Nick Name for this connection. If no formatted nick name has been registered with the TOC server, then the username provided to the logIn call is returned + * @return The Nick Name associated with this connection + */ + public String getNickName() { + return(nickName); + } + + /** login to the TOC server. {@link #connect() } method should be called first + * @param username The username to log in with + * @param password the password for the specified username + * @param waitTime time in milliseconds for successful login before declaring an error + * @throws IOException If a network error occurs + * @throws JaimException If a login failure occurs or login fails to complete before waittime expires + */ + public void logIn(String username,String password,int waitTime) throws JaimException, IOException { + if (connected) { + + nickName=username; + String nuser=Utils.normalise(username); + FLAPSignonFrame sof = new FLAPSignonFrame(); + sof.setSequence(clientSequence++); + sof.setFLAPVersion(1); + sof.setTLVTag(1); + sof.setUserName(nuser); + sout.write(sof.getFrameData()); + TocSignonCommand soc=new TocSignonCommand(host,port,username,password); + sendTocCommand(soc); + for (int i=0;i65535) + clientSequence=0; + return(seq); + } + + private void sendKeepAlive() throws IOException { + FLAPKeepAliveFrame fr=new FLAPKeepAliveFrame(); + fr.setSequence(nextSequence()); + if (debug) { + System.out.println("Sending keepalive"); + } + sout.write(fr.getFrameData()); + } + /** The run method for the dispatcher thread + */ + + public void run() { + while (true) { + + if (messageQueue.size()>0) { + realDispatch((FLAPFrame)messageQueue.remove(0)); + } + else { + if (System.currentTimeMillis()-lastKeepAlive>WAIT_TIME) + { + if (debug) + { + System.out.println("No keepalive received - sending"); + } + try + { + sendKeepAlive(); + lastKeepAlive=System.currentTimeMillis(); + } + catch (IOException ioe) + { + connectionLost(); + } + } + + try { + synchronized(this) { + this.wait(WAIT_TIME); + } + } + catch (InterruptedException e) { + } + } + } + } + + protected void Dispatch(FLAPFrame fr) { + messageQueue.addElement(fr); + synchronized(this) { + this.notify(); + } + } + + + private void realDispatch(FLAPFrame fr) { + switch (fr.getFLAPFrameType()) { + case FLAPFrame.FLAP_FRAME_ERROR: + + try { + disconnect(); + } + catch (IOException e) { + } + break; + case FLAPFrame.FLAP_FRAME_DATA: + + FLAPDataFrame df=(FLAPDataFrame)fr; + TocResponse tr = TocResponseFactory.createResponse(df.getContent()); + HandleTocResponse(tr); + break; + case FLAPFrame.FLAP_FRAME_KEEP_ALIVE: + if (debug) { + System.out.println("Received keep alive frame "+DateFormat.getTimeInstance().format(new Date())); + } + lastKeepAlive=System.currentTimeMillis(); + try + { + sendKeepAlive(); + } + catch (IOException e) + { + connectionLost(); + } + break; + case FLAPFrame.FLAP_FRAME_SIGNOFF: + connected=false; + loggedIn=false; + try { + s.close(); + } + catch (IOException e) { + } + break; + default: + if (debug) { + System.out.println("Unknown type received: "+fr.getFLAPFrameType()); + } + break; + } + } + + + protected void HandleTocResponse(TocResponse tr) { + if (debug) { + System.out.println("Toc Response received:"+tr.toString()); + } + if (tr instanceof SignOnTocResponse) { + TocInitDoneCommand tid = new TocInitDoneCommand(); + TocAddBuddyCommand tab = new TocAddBuddyCommand(); + Iterator it=watchedBuddies.keySet().iterator(); + while (it.hasNext()) { + tab.addBuddy((String)it.next()); + } + try { + sendTocCommand(tab); + sendTocCommand(tid); + deliverEvent(new LoginCompleteTocResponse()); // nform clients that login processing is now complete + loginComplete=true; + } + catch (IOException e) { + } + } + else if (tr instanceof ConfigTocResponse) { + if (debug) { + System.out.println("Received ConfigTocResponse"); + } + + ConfigTocResponse ctr=(ConfigTocResponse)tr; + Enumeration e=ctr.enumerateGroups(); + while (e.hasMoreElements()) { + Group g=(Group)e.nextElement(); + groups.put(g.getName(),g); + Enumeration be=g.enumerateBuddies(); + while (be.hasMoreElements()) { + Buddy b=(Buddy)be.nextElement(); + if (!buddies.containsKey(b.getName())) { + buddies.put(b.getName(),b); + } + } + } + configValid=true; + } + + deliverEvent(tr); + + + + } + + /** Deliver a TocResponse event to registered listeners + *@param tr The TocResponse to be delivered + */ + + private void deliverEvent(TocResponse tr) { + dt.deliverMessage(tr); + + } + + public void joinChat(int exchange, String roomName) { + try { + TocChatJoinCommand joinCommand = new TocChatJoinCommand(exchange, roomName); + sendTocCommand(joinCommand); + } catch (IOException ignore) {} + } + + public void joinChat(String roomName) { + joinChat(4, roomName); + } + + /** Send an instant message + * @param recipient The nickname of the message recipient + * @param msg The message to send + * @throws IOException if a network error occurs + */ + public void sendIM(String recipient,String msg) throws IOException { + sendIM(recipient,msg,false); + } + + /** Send an instant message + * @param recipient The nickname of the message recipient + * @param msg The message to send + * @param auto true if this is an automatic response (eg. away message) + * @throws IOException if a network error occurs + */ + public void sendIM(String recipient,String msg,boolean auto) throws IOException { + + synchronized(this) { + + if (sendPoints < MAX_POINTS) // If we have less than full points + { + long now=System.currentTimeMillis(); + long difference=now-lastMessageSendTime; + sendPoints+=(int)(difference/POINT_RECOVERY_TIME); // 1 point is regained every 2 seconds + if (sendPoints >MAX_POINTS) + sendPoints=MAX_POINTS; + + if (sendPoints group.getBuddyCount()||pos==-1) { + group.addBuddy(buddy); + } + else { + group.addBuddy(buddy,pos); + } + return(buddy); + } + + /** Add a buddy to a group. This information can be saved on the server by calling {@link #saveConfig} + * The buddy is added to the end of the group + * @param buddyName The normalised buddy name to add + * @param groupName The name of the group to add this buddy to + * @return The {@link Buddy} object that represents the specified buddy name. + */ + + public Buddy addBuddy(String buddyName, String groupName) { + return(addBuddy(buddyName,groupName,-1)); + } + + /** Add a buddy to the watch list for this connection. + * This method must be called after {@link #connect()} + * It also appears that the login process will not complete unless at least one buddy is added to the watch list + * @param buddy The nickname to add to the watch list + * @throws JaimException if the method is called at the wrong time + * @see JaimEventListener + * @deprecated the {@link #watchBuddy} method should be used instead + */ + public void addBuddy(String buddy) throws JaimException { + watchBuddy(buddy); + + } + + /** Add a buddy to the watch list for this connection. + * This method must be called after {@link #connect()} + * It also appears that the login process will not complete unless at least one buddy is added to the watch list + * @param buddy The nickname to add to the watch list + * @throws JaimException if the method is called at the wrong time + * @see JaimEventListener + */ + public void watchBuddy(String buddy) throws JaimException { + if (loggedIn) { + try { + TocAddBuddyCommand tab = new TocAddBuddyCommand(); + tab.addBuddy(buddy); + sendTocCommand(tab); + } + catch (IOException e) { + throw new JaimException(e.toString()); + } + } + + watchedBuddies.put(buddy,buddy); + + } + + /** Save group/buddy list configuration to the TOC server + * @throws IOException if a network error occurs + */ + + public void saveConfig() throws IOException { + TocSetConfigCommand tsc=new TocSetConfigCommand(); + Iterator it =groups.keySet().iterator(); + while (it.hasNext()) { + Group g = (Group)groups.get(it.next()); + tsc.addGroup(g); + } + sendTocCommand(tsc); + + } + + /** Return the set of groups that have been stored in the TOC server + * The information returned from this method is only valid if {@link #isConfigValid} returns true + * @return A Collection of {@link Group} Objects + */ + + public Collection getGroups() { + return(groups.values()); + } + + /** + * Return a group, given its name + * @return A {@link Group} Object corresponding to the string name + */ + + public Group getGroupBy(String name) { + Group result = (Group) groups.get(name); + return result; + } + + + /** Indicate whether configuration information has been received from the TOC server. + * If this method returns true then the information returned by {@link #getGroups} is valid + * @return true if configuration information has been received from the TOC server. + */ + + public boolean isConfigValid() { + return(configValid); + } + + /** Send a warning or "Evil" to another user. You must be involved in a communication with a user before you can warn them + * @param buddy The nickname of the buddy to warn + * @param anonymous true if the warning should be sent anonymously + * @throws IOException if a network error occurs + */ + public void sendEvil(String buddy,boolean anonymous) throws IOException { + TocEvilCommand ec=new TocEvilCommand(buddy,anonymous); + sendTocCommand(ec); + } + + + /** Set the information for the logged in user + * @param information The information for this user (May contain HTML) + * @throws IOException if a network error occurs + */ + public void setInfo(String information) throws IOException { + TocSetInfoCommand sic=new TocSetInfoCommand(information); + sendTocCommand(sic); + } + + /** Get the information for the specified user + * @param username The screenname for whom info is requested (May contain HTML) + * @throws IOException if a network error occurs + */ + public void getInfo(String username) throws IOException { + TocGetInfoCommand gic=new TocGetInfoCommand(username); + sendTocCommand(gic); + } + + /** Get an Input stream associated with a URL returned by the "GOTO_URL" toc response + *@param file The "file" returned by calling GotoTocResponse#getURL + *@return An InputStream connected to the specified URL + *@throws IOException if an IO error occurs + *@throws MalformedURLException if there is an error building the URL + */ + + + public InputStream getURL(String file) throws IOException, MalformedURLException { + URL URL; + + URL=new URL("http",host,port,file); + + return(URL.openStream()); + } + + + + /** Set the information for the logged in user + * @param awayMsg The away message for this user. May contain HTML. To cancel "away" status set the awayMsg to "" + * @throws IOException if a network error occurs + */ + public void setAway(String awayMsg) throws IOException { + TocSetAwayCommand sic=new TocSetAwayCommand(awayMsg); + sendTocCommand(sic); + } + + + /** Adds the specified buddy to your permit list. + * @param buddy The buddy to add to your block list. If this is an empty string, mode is changed to "permit none" + * @throws JaimException if a network error occurs + */ + public void addPermit(String buddy) throws JaimException { + if (loggedIn) { + try { + TocAddPermitCommand tap = new TocAddPermitCommand(); + tap.addPermit(buddy); + sendTocCommand(tap); + } + catch (IOException e) { + throw new JaimException(e.toString()); + } + } + } + + /** Adds the specified buddy to your block list. + * @param buddy The buddy to add to your block list. If this is an empty string, mode is changed to "deny none" + * @throws JaimException if a network error occurs + */ + public void addBlock(String buddy) throws JaimException { + if (loggedIn) { + try { + TocAddDenyCommand tad = new TocAddDenyCommand(); + tad.addDeny(buddy); + sendTocCommand(tad); + } + catch (IOException e) { + throw new JaimException(e.toString()); + } + } + } + + /** Called by receiver thread to indicate that the connection has been terminated by an IOException + */ + + private void connectionLost() { + deliverEvent(new ConnectionLostTocResponse()); + logOut(); + connected=false; + } + + + + /** Set the idle time for this user + * @param idleSecs The number of seconds the user has been idle for. Set to 0 to indicate current activity. The server will increment the idle time if non-zero + * @throws IOException if a network error occurs + */ + public void setIdle(int idleSecs) throws IOException { + TocSetIdleCommand sic=new TocSetIdleCommand(idleSecs); + sendTocCommand(sic); + } + + + /** Delete a buddy from the buddy watch list. The buddy should have been added with {@link #addBuddy } first. + * The buddy list can only be modified after {@link #connect } is called. + * @param buddy The buddy name to be deleted\ + * @deprecated use {@link #unwatchBuddy } instead + */ + public void deleteBuddy(String buddy) { + unwatchBuddy(buddy); + } + + /** Delete a buddy from the buddy watch list. The buddy should have been added with {@link #addBuddy } first. + * The buddy list can only be modified after {@link #connect } is called. + * @param buddy The buddy name to be deleted + */ + public void unwatchBuddy(String buddy) { + watchedBuddies.remove(buddy); + } + + private class ReceiverThread extends Thread { + private InputStream sin; + private boolean exit; + private JaimConnection parent; + + private ReceiverThread(JaimConnection parent) { + this.parent=parent; + exit=false; + } + + private void setInputStream(InputStream in) { + sin=in; + } + + public void run() { + if (debug) { + System.out.println("Receiver starting"); + } + FLAPInputFrame inframe=new FLAPInputFrame(); + try { + while (!exit) { + try { + int i; + while ( !inframe.completeFrameRead()) { + i=sin.read(); + inframe.addFrameData((byte)i); + } + try { + FLAPFrame fr=FLAPFrameFactory.createFLAPFrame(inframe.getFrameData()); + parent.Dispatch(fr); + } + catch (FLAPFrameException ffe) { + if (debug) { + ffe.printStackTrace(); + } + } + if (inframe.completeFrameRead()) { + inframe.resetInputFrame(); + } + } + catch (InterruptedIOException iie) { + // We expect these because we are performing reads with a timeout + } + } + } + catch (IOException e) { + connectionLost(); // Indicate that we have lost our connection + if (debug) { + e.printStackTrace(); + } + } + } + + private void pleaseExit() { + exit=true; + } + + } + private class DeliveryThread extends Thread { + private Vector messages; + private boolean exit; + private DeliveryThread() { + messages=new Vector(); + exit=false; + } + + private void deliverMessage(TocResponse tr) { + synchronized(this) { + messages.add(tr); + this.notify(); + } + } + + public void run() { + if (debug) { + System.out.println("Delivery Thread starting"); + } + while (!exit) { + if (messages.size()>0) { + TocResponse tr=(TocResponse)messages.remove(0); + doDelivery(tr); + } + else { + synchronized(this) { + try + { + this.wait(); + } + catch (InterruptedException e) + { + } + } + } + + } + } + + private void doDelivery(TocResponse tr) { + for (int i=0;iJaimException without detail message. + */ + public JaimException() { + } + + + /** + * Constructs an JaimException with the specified detail message. + * @param msg the detail message. + */ + public JaimException(String msg) { + super(msg); + } +} + + diff --git a/src/com/wilko/jaim/JaimStateException.java b/src/com/wilko/jaim/JaimStateException.java new file mode 100644 index 0000000..621350b --- /dev/null +++ b/src/com/wilko/jaim/JaimStateException.java @@ -0,0 +1,44 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $version: $ + */ +public class JaimStateException extends JaimException { + + /** + * Creates new JaimStateException without detail message. + */ + public JaimStateException() { + } + + + /** + * Constructs an JaimStateException with the specified detail message. + * @param msg the detail message. + */ + public JaimStateException(String msg) { + super(msg); + } +} + + diff --git a/src/com/wilko/jaim/JaimTimeoutException.java b/src/com/wilko/jaim/JaimTimeoutException.java new file mode 100644 index 0000000..4dfb271 --- /dev/null +++ b/src/com/wilko/jaim/JaimTimeoutException.java @@ -0,0 +1,45 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +package com.wilko.jaim; + +/** + * + * @author paulw + * @version $version: $ + */ +public class JaimTimeoutException extends JaimException { + + /** + * Creates new JaimTimeoutException without detail message. + */ + public JaimTimeoutException() { + } + + + /** + * Constructs an JaimTimeoutException with the specified detail message. + * @param msg the detail message. + */ + public JaimTimeoutException(String msg) { + super(msg); + } +} + + diff --git a/src/com/wilko/jaim/LoginCompleteTocResponse.java b/src/com/wilko/jaim/LoginCompleteTocResponse.java new file mode 100644 index 0000000..c00fc07 --- /dev/null +++ b/src/com/wilko/jaim/LoginCompleteTocResponse.java @@ -0,0 +1,50 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * LoginCompleteTocResponse.java + * + * Created on November 2, 2002, 2:52 PM + */ + +package com.wilko.jaim; + +/** + * This is a "pseudo" TOC response - it is delivered to JaimLib clients to indicate that login processing has been completed successfully. + * @author wilko + * @version: $revision: $ + */ +public class LoginCompleteTocResponse extends TocResponse { + + public static final String RESPONSE_TYPE="LOGINCOMPLETE"; + + /** Creates a new instance of LoginCompleteTocResponse */ + public LoginCompleteTocResponse() { + } + + public String getResponseType() { + return (RESPONSE_TYPE); + } + + public String toString() + { + return (RESPONSE_TYPE); + } + +} diff --git a/src/com/wilko/jaim/NickTocResponse.java b/src/com/wilko/jaim/NickTocResponse.java new file mode 100644 index 0000000..e288bfd --- /dev/null +++ b/src/com/wilko/jaim/NickTocResponse.java @@ -0,0 +1,82 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * NickTocResponse.java + * + * Created on 6 May 2002, 17:21 + */ + +package com.wilko.jaim; + +/** +* The NicTocResponse is used internally to manage the TOC signon process. It is not delivered to clients of {@link JaimConnection} + * @author paulw + * @version $Revision: 1.6 $ + */ +public class NickTocResponse extends TocResponse implements TocResponseHandler { + + private String nickName; + + public static final String RESPONSE_TYPE="NICK"; + + + /** Creates new NickTocResponse */ + public NickTocResponse() { + nickName=""; + } + + + public TocResponse parseString(java.lang.String str) { + NickTocResponse tr=new NickTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + int colonPos=str.indexOf(':'); + + if (colonPos != -1) + { + nickName=str.substring(colonPos+1); + } + + + } + + public String getNickName() + { + return(nickName); + } + + + public String getResponseType() { + return RESPONSE_TYPE; + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/SignOnTocResponse.java b/src/com/wilko/jaim/SignOnTocResponse.java new file mode 100644 index 0000000..f4fd5d6 --- /dev/null +++ b/src/com/wilko/jaim/SignOnTocResponse.java @@ -0,0 +1,80 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * SignOnTocResponse.java + * + * Created on 4 May 2002, 13:29 + */ + +package com.wilko.jaim; + +/** + * The SignOnTocResponse is used internally to manage the TOC signon process. It is not delivered to clients of {@link JaimConnection} + * @author paulw + * @version $Revision: 1.5 $ + */ +public class SignOnTocResponse extends TocResponse implements TocResponseHandler { + + String version; + + public static final String RESPONSE_TYPE="SIGN_ON"; + + + /** Creates new SignOnTocResponse */ + public SignOnTocResponse() { + version=""; + } + + public String getResponseType() { + return(RESPONSE_TYPE); + } + + protected String getVersion() + { + return(version); + } + + + public TocResponse parseString(String str) + { + SignOnTocResponse tr=new SignOnTocResponse(); + tr.doParse(str); + return(tr); + } + + private void doParse(String str) + { + cmd=str; + int colonpos=str.indexOf(':'); + if (colonpos != -1) + { + version=str.substring(colonpos+1); + } + } + + /** Returns true if this response handler can handle the specified response. + * @param Response - the response string from TOC. This is the part of the response before the first ':' + * @return true if the response can be handled + */ + public boolean canHandle(String Response) { + return(Response.equalsIgnoreCase(RESPONSE_TYPE)); + } + +} diff --git a/src/com/wilko/jaim/TocAddBuddyCommand.java b/src/com/wilko/jaim/TocAddBuddyCommand.java new file mode 100644 index 0000000..d4a6566 --- /dev/null +++ b/src/com/wilko/jaim/TocAddBuddyCommand.java @@ -0,0 +1,67 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * TocAddBuddyCommand.java + * + * Created on 4 May 2002, 13:57 + */ + +package com.wilko.jaim; + +import java.util.Vector; + +/** + * + * @author paulw + * @version $Revision: 1.3 $ + */ +public class TocAddBuddyCommand extends TocCommand { + + private static String CMD="toc_add_buddy"; + + Vector buddyList; + + /** Creates new TocAddBuddyCommand */ + public TocAddBuddyCommand() { + buddyList=new Vector(); + } + + public void addBuddy(String buddy) + { + buddyList.add(Utils.normalise(buddy)); + } + + public String toString() + { + StringBuffer output=new StringBuffer(CMD); + for (int i=0;i= '0' && c<='9')||(c>='a' && c<='z')) + { + output.append(c); + } + } + + return(output.toString()); + } + + /** Roast a password using the AOL roasting protocol + * @param password The password to be roasted + * @return The roasted password + */ + public static String roast(java.lang.String password) { + char[] hexChars={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + + StringBuffer temppw=new StringBuffer(); + temppw.append("0x"); + for (int i=0;i>4)&0x0f]); + temppw.append(hexChars[roastedByte&0x0f]); + } + return(temppw.toString()); + } + + /** This method performs a simple HTML strip on text. It looks for < characters and then skips input until a matching > is found. + * This may fail if the HTML tag contains an embedded '>' + * @param input The text to have HTML stripped + * @return The text stripped of html + */ + public static String stripHTML(java.lang.String input) + { + StringBuffer output=new StringBuffer(); + boolean inHTML=false; + for (int i=0;i') { + inHTML=false; + } + else + { + if (!inHTML) + { + output.append(c); + } + } + } + } + return(output.toString()); + } + + + /** Encode a text message so that it is suitable for transmission using toc_send_im + * + * @param input The text to be encoded + * @return The encoded text + */ + public static String encodeText(String input) + { + StringBuffer output=new StringBuffer("\""); + for (int i=0;i + + + + + + diff --git a/src/com/wilko/jaimtest/JaimTest.java b/src/com/wilko/jaimtest/JaimTest.java new file mode 100644 index 0000000..428949a --- /dev/null +++ b/src/com/wilko/jaimtest/JaimTest.java @@ -0,0 +1,243 @@ +/* + * (C) 2002 Paul Wilkinson wilko@users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + * JaimTest.java + * + * Created on 3 May 2002, 12:26 + */ + +package com.wilko.jaimtest; + +import java.net.*; +import java.io.*; + +import com.wilko.jaim.*; + +import java.util.*; + +/** + * @author paulw + * @version $Revision: 1.13 $ + */ +public class JaimTest implements JaimEventListener { + + JaimConnection c; + + boolean quit = false; + + /** + * Creates new JaimMain + */ + public JaimTest() { + + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + if (args.length < 2) { + System.out.println("Usage: JaimTest "); + } else { + JaimTest tester = new JaimTest(); + tester.doIt(args[0], args[1]); + } + + } + + private void doIt(String username, String password) { + try { + c = new JaimConnection("toc.oscar.aol.com", 9898); + c.setDebug(true); // Send debugging to standard output + c.connect(); + + c.addEventListener(this); + c.watchBuddy("username"); // Must watch at least one buddy or you will not appear on buddy listings + + c.logIn(username, password, 50000); + c.addBlock(""); // Set Deny None + + c.setInfo("This buddy is using Jaim."); + + + c.setIdle(60); // Pretend we have been idle for a minute + c.setAway("I am away right now"); + + try { + Thread.sleep(10000); //Wait for 10 second + } catch (InterruptedException ie) { + } + + c.setIdle(0); // Pretend we have been idle for a minute + c.setAway(""); + + while (!quit) { + try { + Thread.sleep(300000); //Wait for 5 minutes + } catch (InterruptedException ie) { + } + } + System.out.println("Disconnecting"); + c.disconnect(); + + } catch (IOException e) { + e.printStackTrace(); + } catch (JaimException je) { + je.printStackTrace(); + } + + } + + /** + * Receive an event and process it according to its content + * + * @param event - The JaimEvent to be processed + */ + + + public void receiveEvent(JaimEvent event) { + TocResponse tr = event.getTocResponse(); + String responseType = tr.getResponseType(); + System.out.println("Type: " + responseType); + if (responseType.equalsIgnoreCase(BuddyUpdateTocResponse.RESPONSE_TYPE)) { + receiveBuddyUpdate((BuddyUpdateTocResponse) tr); + } else if (responseType.equalsIgnoreCase(IMTocResponse.RESPONSE_TYPE)) { + receiveIM((IMTocResponse) tr); + } else if (responseType.equalsIgnoreCase(EvilTocResponse.RESPONSE_TYPE)) { + receiveEvil((EvilTocResponse) tr); + } else if (responseType.equalsIgnoreCase(GotoTocResponse.RESPONSE_TYPE)) { + receiveGoto((GotoTocResponse) tr); + } else if (responseType.equalsIgnoreCase(ConfigTocResponse.RESPONSE_TYPE)) { + receiveConfig(); + } else if (responseType.equalsIgnoreCase(ErrorTocResponse.RESPONSE_TYPE)) { + receiveError((ErrorTocResponse) tr); + } else if (responseType.equalsIgnoreCase(LoginCompleteTocResponse.RESPONSE_TYPE)) { + System.out.println("Login is complete"); + } else if (responseType.equalsIgnoreCase(ConnectionLostTocResponse.RESPONSE_TYPE)) { + System.out.println("Connection lost!"); + } else if (responseType.equalsIgnoreCase(ChatInviteTocResponse.RESPONSE_TYPE)) { + recieveChatInvite((ChatInviteTocResponse) tr); + } else { + System.out.println("Unknown TOC Response:" + tr); + } + } + + private void receiveError(ErrorTocResponse et) { + System.out.println("Error: " + et.getErrorDescription()); + } + + private void receiveIM(IMTocResponse im) { + System.out.println(im.getFrom() + "->" + Utils.stripHTML(im.getMsg())); + + try { + + c.sendIM(im.getFrom(), "Hello " + im.getFrom(), false); + + } catch (IOException e) { + } + } + + private void receiveBuddyUpdate(BuddyUpdateTocResponse bu) { + System.out.println("Buddy update: " + bu.getBuddy()); + if (bu.isOnline()) { + System.out.println("Online"); + } else { + System.out.println("Offline"); + } + + if (bu.isAway()) { + System.out.println("Away"); + } + + System.out.println("evil: " + bu.getEvil()); + + System.out.println("Idle: " + bu.getIdleTime()); + + System.out.println("On since " + bu.getSignonTime().toString()); + } + + private void receiveEvil(EvilTocResponse er) { + if (er.isAnonymous()) { + System.out.println("We have been warned anonymously!"); + } else { + System.out.println("We have been warned by " + er.getEvilBy()); + try { + c.sendEvil(er.getEvilBy(), false); // Let's warn them back + c.addBlock(er.getEvilBy()); // And block them + } catch (Exception e) { + e.printStackTrace(); + } + } + + System.out.println("New warning level is:" + er.getEvilAmount()); + } + + private void receiveGoto(GotoTocResponse gr) { + System.out.println("Attempting to access " + gr.getURL()); + try { + InputStream is = c.getURL(gr.getURL()); + if (is != null) { + InputStreamReader r = new InputStreamReader(is); + int chr = 0; + while (chr != -1) { + chr = r.read(); + System.out.print((char) chr); + } + + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void recieveChatInvite(ChatInviteTocResponse inviteTocResponse) { + c.joinChat(inviteTocResponse.getRoomName()); + } + + private void receiveConfig() { + System.out.println("Config is now valid."); + + try { + Iterator it = c.getGroups().iterator(); + while (it.hasNext()) { + Group g = (Group) it.next(); + System.out.println("Group: " + g.getName()); + Enumeration e = g.enumerateBuddies(); + while (e.hasMoreElements()) { + Buddy b = (Buddy) e.nextElement(); + b.setDeny(false); + b.setPermit(false); + c.watchBuddy(b.getName()); + if (b.getDeny()) { + c.addBlock(b.getName()); + } + if (b.getPermit()) { + c.addPermit(b.getName()); + } + } + } + c.saveConfig(); + } catch (Exception je) { + je.printStackTrace(); + } + } + + +}