Mercurial > pidgin.yaz
changeset 1152:201ec77f3a60
[gaim-migrate @ 1162]
icq. whoop de doo
committer: Tailor Script <tailor@pidgin.im>
line wrap: on
line diff
--- a/ChangeLog Tue Nov 28 00:53:27 2000 +0000 +++ b/ChangeLog Tue Nov 28 02:22:42 2000 +0000 @@ -2,7 +2,10 @@ version 0.11.0: * Multiple connections - * Protocol plugins (IRC (plugins/irc.c), Yahoo (plugins/yay)) + * Protocol plugins: + IRC (plugins/irc.c) + Yahoo (plugins/yay) + ICQ (plugins/icq) * Logs now stored to ~/.gaim/logs rather than ~/.gaim/SN/ * User configurable sounds * Scroll bar now functions properly in chat room user lists
--- a/FIXME Tue Nov 28 00:53:27 2000 +0000 +++ b/FIXME Tue Nov 28 02:22:42 2000 +0000 @@ -1,3 +1,2 @@ GAIM: Items to be fixed ------------------------ -do Buddy Pounces on a per-connection basis
--- a/configure.in Tue Nov 28 00:53:27 2000 +0000 +++ b/configure.in Tue Nov 28 02:22:42 2000 +0000 @@ -197,6 +197,7 @@ sounds/Makefile plugins/Makefile plugins/yay/Makefile + plugins/icq/Makefile pixmaps/Makefile libfaim/Makefile po/Makefile.in
--- a/plugins/Makefile.am Tue Nov 28 00:53:27 2000 +0000 +++ b/plugins/Makefile.am Tue Nov 28 02:22:42 2000 +0000 @@ -5,7 +5,7 @@ if PLUGINS -SUBDIRS = yay +SUBDIRS = yay icq plugin_DATA = autorecon.so iconaway.so irc.so notify.so spellchk.so lagmeter.so plugindir = $(libdir)/gaim
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/.cvsignore Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,24 @@ +Makefile +.deps +.libs +chatsession.lo +contacts.lo +cyrillic.lo +filesession.lo +icqbyteorder.lo +icqlib.lo +icqpacket.lo +list.lo +proxy.lo +queue.lo +stdpackets.lo +tcp.lo +tcpchathandle.lo +tcpfilehandle.lo +tcphandle.lo +tcplink.lo +udp.lo +udphandle.lo +util.lo +gaim_icq.lo +libgaimicq.la
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/AUTHORS Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,9 @@ +Core Developers +--------------- +Denis V. Dmitrienko <denis@null.net> +Bill Soudan <soudan@kde.org> + +Secondary Developers +-------------------- +Vadim Zaliva <lord@crocodile.org> +Nikita I. Makeev <whale@nichego.net> (retired ;)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/COPYING Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 + + Appendix: 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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. + + <signature of Ty Coon>, 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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/ChangeLog Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,975 @@ +2000-07-30 Denis V. Dmitrienko <denis@null.net> + + * ChangeLog, icqlib-0.2.0.lsm, icqlib-1.0.0.lsm, README, TODO, + VERSION, Win32.zip: + Updated version for 1.0.0 release. + +2000-07-25 Denis V. Dmitrienko <denis@null.net> + + * README: Description was changed a little. + + * icqlib/icq.h.in: Cleanups. + +2000-07-23 Bill Soudan <soudan@kde.org> + + * README: added description + + * icqlib/icq.h.in, icqlib/icqlib.c, icqlib/tcpchathandle.c, + icqlib/tcpfilehandle.c: added support for real nickname during + TCP transactions like file and chat, instead of using Bill + all the time (hmm, where'd I get that from? :) + +2000-07-22 Denis V. Dmitrienko <denis@null.net> + + * AUTHORS, DEVEL, icqlib-0.1.3.lsm, icqlib-0.2.0.lsm, README, TODO: + Text files in root directory were changed to reflect latest changes. + +2000-07-22 Denis V. Dmitrienko <denis@null.net> + + * icqlib/util.c: Trinidad and Tobago country was added. + + * icqlib/icq.h.in: Cleanups. + +2000-07-21 Denis V. Dmitrienko <denis@null.net> + + * icqlib/util.c: All languages, possible in original icq were added. + Occupation array fixed. + +2000-07-20 Denis V. Dmitrienko <denis@null.net> + + * icqlib/util.c: + Occupation table corrected to comply with original ICQ. + +2000-07-09 Bill Soudan <soudan@kde.org> + + * icqlib/list.c: added more trace messages, added list_remove_node + call in list_free... fixes list corruption bug introduced + during last commit + + * icqlib/queue.c: added more trace messages, reworked packet + delete handling: now happens during _icq_UDEQueueItemFree rather + than during icq_UDPQueueDelSeq - fixes memory leak + +2000-07-09 Bill Soudan <soudan@kde.org> + + Cleanups, and nasty memory bug fixes. Hopefully this will + correct the strange crashes Denis is having after the icq_Done + call! + + The major problem was: icq_TCPLinkDelete and icq_FileSessionDelete + were calling list_remove to remove themselves from the global + TCPLink and FileSession lists kept in ICQLINK. But, these + functions were being called from a list_delete call also, + in icq_TCPDone, so what was happening is the list_nodes were + getting free()ed twice! + + This problem was circumvented by removing the list_remove + from the *Delete functions, and creating new Close functions + that do the list_remove and then call the corresponding + Delete function. + + * icqlib/chatsession.c, icqlib/chatsession.h, icqlib/filesession.c, + icqlib/tcp.c, icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c, + icqlib/tcplink.c, icqlib/tcplink.h, icqlib/udp.c, + icqlib/stdpackets.h: adding new *Close functions, use *Close + functions instead of *Delete where correct, and misc cleanups + + * icqlib/icq.h.in: removed unnecessary members from ICQLINK + + * icqlib/icqlib.c, icqlib/icqlib.h: removed unnecessary + functions + + * icqlib/list.c, icqlib/list.h: recoded list_free function - this + was working very incorrectly! it was only freeing the first + node of the list, and then ending. fixes a memory leak. + + * icqlib/queue.c: use new list_free + + * icqlib/tcp.c: use Close functions, misc cleanups + +2000-07-09 Denis V. Dmitrienko <denis@null.net> + + * icqlib/icq.h.in: Cleanups. + + * icqlib/icqlib.c: + Initial memset() in icq_Init() replaced by callback's clearance. + + * icqlib/udp.c: + icq_UpdateNewUserInfo() now returns seq1 instead of seq2 since it + isn't META function. + +2000-07-07 Denis V. Dmitrienko <denis@null.net> + + * icqlib/icqpacket.c: + "icq_Packet data overflow" log message temporarily commented out. + +2000-07-04 Paul Cadach <paul@odt.east.telecom.kz> + * icqlib/utilc: + icq_FmtLog() crashed when it receives NULL at link argument. + +2000-06-30 Denis V. Dmitrienko <denis@null.net> + + * icqlib/util.c: Slovak Republic country code fixed. + +2000-06-25 Denis V. Dmitrienko <denis@null.net> + + * icqlib/udphandle.c: + icq_HandleMetaUserInfo() handles all (!) available in original icq2k + Meta User Info packets along with other useful Meta* packets. (WOW! ;) + + * icqlib/icq.h.in: + New callbacks (we really need an event-driven model later): + icq_MetaUserFound, icq_MetaUserInfo, icq_MetaUserWork, + icq_MetaUserMore, icq_MetaUserAbout, icq_MetaUserInterests, + icq_MetaUserAffiliations, icq_MetaUserHomePageCategory + New functions-companions for Meta User Info: + icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(), + icq_GetMetaAffiliationName(), icq_GetMetaLanguageName() + New function to request Meta User Info icq_SendMetaInfoReq() + COUNTRY_CODE was "generalized" to icq_ArrayType. Note: this is + source incompatible change! + + * icqlib/util.c: icq_MetaOccupation[], icq_MetaPastBackgrounds[], + icq_MetaAffiliations[] and icq_MetaLanguages[] arrays were added along + with icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(), + icq_GetMetaAffiliationName() and icq_GetMetaLanguageName() functions + to access them. + + * icqlib/udp.h: Some META* defines changed/added. + USER_INFO structure which is never been used now removed. + + * icqlib/udp.c: icq_SendMetaInfoReq() was added. + All icq_*Meta*() functions now returns sequence number 2 because their + replies from the server are synced with it. + + * icqlib/tcphandle.c, icqlib/tcpfilehandle.c, icqlib/eventhandle.c: + '\n' was added at the end of log messages. + + * icqlib/queue.c: + Some sanity checks were added to icq_UDPQueueDelete() and + icq_UDPQueueFree() + + * icqlib/icqpacket.c: icq_PacketUDPDump() tweaked a little. + +2000-06-17 Denis V. Dmitrienko <denis@null.net> + + * icqlib/contacts.c, icqlib/icq.h.in: + New parameter was added in icq_ContactSetVis() for setting/resetting + 'Visible to User' status. + Port's type was changed to unsigned short in icq_UserOnline callback. + +2000-06-15 Bill Soudan <soudan@kde.org> + + * icqlib/icqevent.c, icqlib/icqevent.h, icqlib/eventhandle.c, + icqlib/eventhandle.h: committed for safekeeping, not used yet. + this code will soon replace stdpackets.c and tcphandle.c, as + well as reducing code duplication in many other places. hopefully + it can eventually be extended to manage udp events as well, as + it's written in pseudo-object-oriented style. + +2000-06-14 Bill Soudan <soudan@kde.org> + + Bugfixes and code cleanups. + + * icqlib/filesession.c, icqlib/filesession.h: added id arg to + icq_FindFileSession to allow searches for specific file session + + * icqlib/icq.h.in: removed *Seq functions, renamed chat req functions + to be consistent with file req functions, added Cancel and Refuse + functions for chat and file reqs + + * icqlib/queue.h: added proto for icq_UDPQueueInterval + + * icqlib/stdpackets.c, icqlib/stdpackets.h: added creation + functions for cancel and refuse operations + + * icqlib/tcp.c, icqlib/tcp.h: added Cancel and Refuse functions + for chat and file reqs, changed packet sending code to use new + icq_TCPLinkSendSeq function to elimitane duplicate code, removed + *Seq functions, renamed chat req functions + + * icqlib/tcpfilehandle.c: fixed bug: sending file sessions would + freeze if remote side changed speed + + * icqlib/tcplink.c, icqlib/tcplink.h: added icq_TCPLinkSendSeq + function + + * icqlib/icqlib.c, icqlib/udp.c: removed *Seq functions + +2000-05-21 Denis V. Dmitrienko <denis@null.net> + + * icqlib/util.c: Bulgaria country code was added. Thanks to + "Napalm Death" <napalmbox@hotmail.com> + + * icqlib/cyrillic.c: Applied patch for russian letters IO and io by + Vladimir Eltchinov <elik@design.ru> + +2000-05-10 Denis V. Dmitrienko <denis@null.net> + + * icqlib/icq.h.in, icqlib/icqlib.c, icqlib/queue.c, + icqlib/queue.h, icqlib/udp.c: + UDP outgoing packet queue was implemented. + + * icqlib/udphandle.c, icqlib/proxy.c: + icq_Disconnect() now called before icq_Disconnected callback to + prevent high CPU usage in kicq's "reconnect on disconnect" code. + + * icqlib/list.c, icqlib/list.h: + list_free() was added to free but do not dispose the list. + Memory leak with destroying the list was fixed. + +2000-05-05 Denis V. Dmitrienko <denis@null.net> + + * Win32.zip: + Automatically generated icq.h repackaged for Win32 portability. + +2000-05-04 Bill Soudan <soudan@kde.org> + + * icqlib/tcp.h: undefined TCP debug trace constants in preparation + for release. + + * icqlib/stdpackets.c: warning cleanups. + + * icqlib/icq.h.in: changed FILE_STATUS_* defines, removed + many ICQ_NOTIFY_FILE* defines, added new direction member + to icq_FileSession, removed unnecessary uin arg from + icq_FileSessionSetSpeed. + + * icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c, icqlib/tcphandle.c, + icqlib/tcplink.c, icqlib/filesession.c, icqlib/tcp.c: + Reworked file transfer notification, small bugfixes, + and cleanups. + +2000-05-03 Denis V. Dmitrienko <denis@null.net> + + * icqlib/udp.c: icq_UpdateNewUserInfo() was added. + All icq_UpdateMetaInfo*() now return their sequence number. + + * icqlib/chatsession.c, icqlib/filesession.c, icqlib/icq.h.in, + icqlib/Makefile.am, icqlib/proxy.c, icqlib/tcpchathandle.c, + icqlib/tcpfilehandle.c, icqlib/tcphandle.c, icqlib/tcplink.c, + icqlib/udphandle.c, icqlib/util.c, icqlib/callbacks.c: + Callbacks have been moved to the ICQLINK structure. + + * icqlib/icqpacket.c, icqlib/icqpacket.h: + icq_PacketReadUDPInUIN() was added. + + * icqlib/list.c: Bug with empty contact list was fixed. + + * icqlib/icqlib.c: Unfinished UDP queue was commented out. + +2000-04-13 Denis V. Dmitrienko <denis@null.net> + + * README.Win32, VC5.zip, Win32.zip: + icq.h header file which is automatically generated on Unix is packaged + in Win32.zip archive along with the Visual C++ 5.0 project file. + +2000-04-10 Denis V. Dmitrienko <denis@null.net> + + * icqlib/chatsession.h, icqlib/filesession.h, icqlib/stdpackets.c, + icqlib/tcp.c, icqlib/tcpfilehandle.c, icqlib/tcplink.c: + ANSI cleanups. + + * icqlib/filesession.c, icqlib/icqlib.c, icqlib/stdpackets.h, + icqlib/tcp.c, icqlib/tcpfilehandle.c, icqlib/tcp.h, + icqlib/tcplink.c, icqlib/udp.c, icqlib/udp.h, icqlib/util.c, + VC5.zip: + Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +2000-04-06 Herbert Valerio Riedel <hvr@gnu.org> + + * icqlib/icq.h.in, icqlib/udp.c (icq_KeepAlive,icq_SendAuthMsg): + return sequence number + +2000-04-06 Denis V. Dmitrienko <denis@null.net> + + * icqlib/icq.h.in, icqlib/icqlib.c, icqlib/stdpackets.c, icqlib/tcp.c: + icq_*Send*Seq() functions with specified sequence number were added. + + * icqlib/udp.c: + So called "Online List problem" bug with Long Contact List was fixed. + icq_*Send*Seq() functions with specified sequence number were added. + +2000-04-05 Denis V. Dmitrienko <denis@null.net> + + * README.Win32, VC5.zip, icqlib/icqbyteorder.h, icqlib/icq.h.in, + icqlib/icqlib.c, icqlib/icqlib.h, icqlib/icqpacket.c, + icqlib/icqtypes.h, icqlib/proxy.c, icqlib/tcp.c, + icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c, + icqlib/tcphandle.c, icqlib/tcplink.c, icqlib/tcplink.h, + icqlib/udp.c, icqlib/util.c, icqlib/util.h: + Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 + compatibility. + +2000-03-31 Igor S. Petrenko <nofate@europe.com> + + * icqlib/util.c: remove static variable + +2000-03-30 Denis V. Dmitrienko <denis@null.net> + + * am_edit, configure.in, libtool.m4.in, ltconfig, ltmain.sh, + missing, mkinstalldirs, acinclude.m4.in, Makefile.cvs: + New autoconf/automake stuff from KDE2. + + * icqlib/queue.c: Fixed FreeBSD warning about obsolete malloc.h + header. + +2000-02-14 Bill Soudan <soudan@kde.org> + + Applied patch from Paul Cadach <paul@odt.east.telecom.kz>. + + * icqlib/icq.h.in: added icq_TCPSendChatData_n + + * icqlib/tcp.c: use new icq_ChatRusConv_n function in + icq_TCPSendChatData, new icq_TCPSendChatData_n function + + * icqlib/tcplink.c, tcplink.h: new icq_ChatRusConv_n function + +2000-02-06 Bill Soudan <soudan@kde.org> + + * icqlib/tcpchathandle.c: warning cleanups. + +2000-02-06 Bill Soudan <soudan@kde.org> + + Applied patch from Paul Cadach <paul@odt.east.telecom.kz>. + Thanks Paul! + + Paul's change list: + + 1) Modified TCP link code to allow non-blocking TCP connects over + SOCKS5 proxy + 2) Added missed Cyrillic translating for Chat subject, URL subject, + File transfer subject (both directions); + 3) Fix a bug in TCPLinkProxyConnect code (remote address was random + due to using local variable instead of plink's remote_address). + + * icqlib/cyrillic.c, icqlib/icqlib.h: added icq_RusConv_n + + * icqlib/stdpackets.c: slightly modified chat packets + + * icqlib/tcp.c: new code for SOCKS connections, more cyrillic + translations + + * icqlib/tcpchathandle.c: new code for special chat functions + (background, fonts, etc) + + * icqlib/tcplink.c: implemented non-blocking TCP connects + over SOCKS, cyrillic translation for chat + + * icqlib/tcplink.h: new defines for SOCKS5 code + + * icqlib/udphandle.c: changed log message in HandleUserOnline + +2000-02-03 Bill Soudan <soudan@kde.org> + + * icqlib/icqlib.h: line 33, fixed minor compile bug, changed + u_int32_t declaration to unsigned long. This was causing a + problem compiling on SunOS, as reported by Longwen + <longwen@mail.com> + +2000-01-20 Bill Soudan <soudan@kde.org> + + Worked more on file send implementation. icqlib will now also + handle sending file requests to clients. + + * icqlib/filesession.c, filesession.h, icq.h.in, stdpackets.c + stdpackets.h, tcp.c, tcpfilehandle.c, tcphandle.c: + first implementation of sending file requests + + * icqlib/tcplink.c: fixed bug in icq_TCPLinkConnect that caused + file/chat connection attempts to go to the wrong port + +2000-01-16 Bill Soudan <soudan@kde.org> + + Exported icq_FileSession structure to library clients; + fixed a serious list bug. Oops. :) + + * icqlib/filesession.c, filesession.h: added new public functions, + icq_FileSessionSetSpeed, icq_FileSessionClose, + icq_FileSessionSetWorkingDir, moved icq_FileSession interface to + icq.h.in + + * icqlib/icq.h.in: added definition for icq_FileSession and new + public functions + + * icqlib/list.c: fixed serious bug in list_remove + + * icqlib/tcp.c: renamed icq_TCPAcceptFileReq to + icq_AcceptFileRequest, moved file request functions to new + file session code + + * icqlib/tcpfilehandle.c: added code so icq_FileSessions now + keep track of the tcplink to which they are attached + + * icqlib/tcplink.h: removed list_node from icq_TCPLink + +2000-01-15 Bill Soudan <soudan@kde.org> + + Reworked list routines so list_node's don't need to be + inside item structures. Note this made the strlist code + unnecessary - strlist code was replaced with generic list + commands. + + * icqlib/Makefile.am: strlist.c, strlist.h removed + + * chatsession.c, chatsession.h, contacts.c, contacts.h, + filesession.c, filesession.h, icqlib.c, icqpacket.c, icqpacket.h, + list.c, list.h, queue.c, queue.h, tcp.c, tcplink.c, tcplink.h, + udphandle.c: reworked list code, removed strlist code + + * strlist.c, strlist.h: removed + +1999-12-27 Bill Soudan <soudan@kde.org> + + * icqlib/icq.h.in: added proto for icq_TCPFileSetSpeed + + * icqlib/icqlib.c: cleanups + + * icqlib/tcp.c: fixed bug in icq_TCPAcceptFileReq, added + icq_TCPFileSetSpeed + + * icqlib/tcplink.c: fixed bug in icq_TCPOnDataReceived, + removed flags variable ;) + +1999-12-27 Denis V. Dmitrienko <denis@null.net> + + * icqlib/udphandle.c, icqlib/udp.h, icqlib/udp.c, icqlib/icq.h.in: + icq_UpdateMetaInfoSecurity() added for setting "My authorization is + required", "Web Aware" and "IP Publishing". + + * icqlib/tcplink.c: Unused "flags" variable commented out. + +1999-12-20 Bill Soudan <soudan@kde.org> + + Worked more on file transfer. icqlib will now write received + files to disk, and handles all transfer details accordingly + after icq_TCPAcceptFileReq is called. Note currently + files are always saved in current directory. Receiving a + single file is working 100% as best I can tell - receiving + multiple files hasn't been tested well but should work. + + Also reworked icq_TCPLinkOnDataRecevied to handle quick, large + streams of data (processing 1 packet every main loop call + just didn't cut it :), and at the same time fixed a bug where + received packets would not get processed if the remote end + closed the connection immediately after sending one. This had + the result that the tcp sockets stay in non-blocking mode + for their entire life, instead of just during connect + as before. + + Resume is currently off-by-one I think. Don't rely on it. + + * icqlib/filesession.[ch]: added file open/close logic, changed + icq_FileSession struct a bit + + * icqlib/icq.h.in: removed unnecessary icq_TCPSendFile??Packet + functions, user programs do not use these + + * icqlib/tcp.[ch]: moved _process_packet logic into tcplink:: + icq_TCPLinkProcessReceived, removed unnecessary + icq_TCPSendFile??Packet functions + + * icqlib/tcpfilehandle.c: added more file transfer logic to + write file to disk + + * icqlib/tcplink.c: added icq_TCPLinkProcessReceived to + support processing receive queue before delete (packets used + to get dropped in this instance, oops), reworked + icq_TCPLinkOnDataReceived to handle quick, large streams + of data, changed icq_TCPLinkOnConnect and *Accept to + make all sockets non-blocking. + +1999-12-13 Bill Soudan <soudan@kde.org> + + Implemeted SF task #10224, use real_ip when our IP and remote + IP are same, and task #10203, connect timeout for tcp requests. + + Fixed bug #100312, double freeing of list item. + + NOTE: masq hack in udphandle.c::icq_HandleUserOnline is now gone! + Updated connect logic _should_ automatically do that for us now. + + * icqlib/contacts.h: added remote_real_ip member to icq_ContactItem + struct + + * icqlib/tcp.c: fixed double delete bug in _handle_ready_sockets, + added code to implement connect timeout + + * icqlib/tcplink.c: icq_TCPLinkConnect now uses real_ip when + our IP is same as remote IP to make connection, added + code to implement connect timeout + + * icqlib/tcplink.h: added TCP_LINK_CONNECT_TIMEOUT constant, + added connect_time to icq_TCPLink struct + + * icqlib/udphandle.c: removed old real_ip->ip masq hack, + added store to remote_real_ip in icq_ContactItem + +1999-12-12 Denis V. Dmitrienko <denis@null.net> + + * icqlib/udphandle.c: Authorization Request packet handling fixed. + + * Makefile.am: DEVEL file included + +1999-12-02 Bill Soudan <soudan@kde.org> + + commited missing filesession.c and filesession.h files. Sorry + 'bout that :) + +1999-11-30 Bill Soudan <soudan@kde.org> + + More file xfer support added. icqlib tcp will now 'go through the + motions' for receiving a file. file data is not written to + disk, yet. + + * icqlib/Makefile.am: added filesession.[ch] + + * icqlib/icq.h.in: new notify constant (ICQ_NOTIFY_FILE), + new icq_FileSessions member in icqlink struct, new AcceptFileReq + prototype + + * icqlib/icqpacket.h: ICQ_PACKET_DATA_SIZE increased to 4096 + to support file transfer packets + + * icqlib/tcp.c: added file session logic + + * icqlib/tcpfilehandle.c: added icq_HandleFileHello + + * icqlib/tcphandle.c: more file xfer logic added + + * icqlib/tcplink.c, tcplink.h: buffer overflow check added, + tcplinks will now close if buffer overflows. increased + icq_TCPLinkBufferSize to 4096 to support file transfer packets + +1999-11-29 Denis V. Dmitrienko <denis@null.net> + + * icqlib/udphandle.c: icq_DoMsg() redone using string lists. + + * icqlib/strlist.c, icqlib/strlist.h: + General interface for string lists added. + + * icqlib/tcplink.c: Absence of socklen_t type fixed. + + * icqlib/icq.h.in, icqlib/callbacks.c: + icq_RecvMailExpress callback added. + + * icqlib/Makefile.am: strlist.[ch] added. + +1999-10-14 Denis V. Dmitrienko <denis@null.net> + + * icq.h.in, udp.c: icq_UpdateMetaInfo* functions added. + +1999-10-07 Denis V. Dmitrienko <denis@null.net> + + * icq.h.in, tcp.h: Internal/external functions declarations + unified a little. + + * kicq/Makefile.am, proxy.c, udp.c: proxy.h file removed. + +1999-10-06 Denis V. Dmitrienko <denis@null.net> + + * DEVEL: Added the "developers' hint guide". Please read it + carefully. + +1999-09-29 Bill Soudan <soudan@kde.org> + + Check out my spiffy new email address! :) + + Renamed all tcp_link* functions to icq_TCPLink*. + + Forgot to note: fixed memory leak in tcp.c (tcp packets were not + being deleted after use... oops :) + + * chatsession.c, tcpchathandle.c, tcpfilehandle.c, tcphandle.c, + chatsession.h: reworked chat/file handling. fixed chat. (it's + been broke since I put non-blocking connects in) + + * Makefile.am: added new files + + * icq.h.in: changed some notification values, added support for + chat sessions to icqlink + + * icqlib.h, udp.h: moved a bunch of udp-only defines to udp.h + + * icqpacket.c, list.c: cleanups + + * tcp.c: cleanups, moved connect logic from _handle_ready_sockets + to icq_TCPLinkOnConnect, tcp_link->icq_TCPLink + + * tcplink.c, tcplink.h: renamed tcp_link* to icq_TCPLink*. many + cleanups, added icq_TCPLinkOnConnect + + * stdpackets.c, stdpackets.h, tcp.h: tcp_link*->icq_TCPLink* + + * udp.c: tcp port wasn't being sent properly in login packet + +1999-09-29 Denis V. Dmitrienko <denis@null.net> + + Show must go on! Hopefully fixed CVS problems. + + * icqlib.c: Host/network/icq byteorder systemized. + icq_Init() cleaned up. + + * acconfig.h, configure.in, icqlib.m4.in, + icqlib/icqbyteorder.[ch]: More optimized byteswap stuff. + + * icqlib.h: LOGIN_*_TCP defines added. + + * icqpacket.[ch]: icq_PacketAppend16n() added for network-ordered + word appending. + + * queue.[ch]: ICQLINK compatibility added. + + * stdpackets.c: Host/network byteorder cleanups. + + * tcplink.c: TCP code SOCKS-ification. Not finished. + + * udp.c: Webaware functions enabled without success even with + UDP v5 - need more investigations. + + * udphandle.c: MailExpress message handler started. + +1999-07-18 Bill Soudan <wes0472@rit.edu> + + fixed tcp problems, changed icq_ContactItem structure to use + list.c and moved to contacts.c, removed old byte swap macros + in favor of new functions in icqbyteorder.c, and added better + log messages + + * Makefile.am: added contacts.c, contacts.h + + * contacts.c, contacts.h: added + + * icq.h.in: moved icq_ContactItem struct to contacts.h, + removed old *Sok members, renamed icq_Cont* functions + + * icqlib.c, icqlib.h: changed to use new byte-order functions & + contact list functions + + * icqpacket.c: changed to use new byte-order functions + + * tcp.c: added better log messages + + * tcplink.c: fixed fail notification bug introduced during ICQLINK + changes, changed to use new byte-order functions & contact list + functions, added better log messages + + * udp.c: changed to use new byte-order functions & + contact list functions + + * udphandle.c: fixed tcp port bug in icq_HandleUserOnline, changed + to use new byte-order & contact list functions + + * util.c, util.h: removed old byte order and contact list + functions + +1999-07-16 Denis V. Dmitrienko <denis@null.net> + + Version changed to 0.2.0 + + * udp.c, udp.h, udphandle.c: ICQ UDP v5 implemented. + Encription for ICQ UDP v5 implemented. + icq_Packet* unified interface for UDP packets implemented. + Multipacket support of ICQ UDP v5 added. + + * util.[ch]: Status support changed to support early unsupported + combined (ORed) statuses. + + * Makefile.am, icqlib/Makefile.am: Remove automatically generated + files by "make maintainer-clean" + +1999-07-02 Vadim Zaliva <lord@crocodile.org> + + * icqlib/udphandle.c (icq_HandleUserOnline): using icqtohl macros + to convert parameters of callback (IP addresses, port #) to host + order. + + * icqlib/icqbyteorder.h: added (per Bill suggestion) defenitions + of icqtohs, icqtons, ntociqs, htociqs macros. + + * icqlib/tcppacket.c: some system header files included to avoid + compilation warnings. + + * icqlib/tcplink.c: some system header files included to avoid + compilation warnings. + + * icqlib/tcp.h: icq_TCPProcessFilePacket prototype added to avoid + compilation warnings. + + * icqlib/tcp.c: add includes to avoid compilation warning for + getsockopt() and some other functions. + + * configure.in: add detection of headers used on Solaris, Linux, + FreeBSD to detect edianness. + + * icqlib/icqbyteorder.h: defenition of icqtohl, icqtonl, ntociql, + htociql macros. + +1999-07-02 Bill Soudan <wes0472@rit.edu> + + icq_SendMessage and icq_SendURL now accept a 3 choice thruSrv arg: + ICQ_SEND_THRUSERVER, ICQ_SEND_DIRECT, or ICQ_SEND_BESTWAY. + added support to icq_ContactItem structure and udphandle.c. + + * icq.h: added new ICQ_SEND_* constants + + * icqlib.c: added new code to support thruSrv arg to SendMessage + and SendURL + + * util.h: added tcp_flag member to icq_ContactItem struct + + * udphandle.c: added code to HandleUserOnline to update tcp_flag + +1999-06-30 Bill Soudan <wes0472@rit.edu> + + implemented non-blocking connects, including checking for failed + connects. failed sends/other networking calls still to do. + + * icq.h: renamed ICQ_NOTIFY_CONNECTFAILED to ICQ_NOTIFY_FAILED + + * list.h, list.c: changed list_traverse to use va_list + + * tcpprocess.c: cleanups + + * tcp.c, tcplink.c, tcplink.h: implemented non-blocking connects +c +1999-05-03 Bill Soudan <wes0472@rit.edu> + + * tcplink.c: removed exit calls + + * callbacks.c, icq.h, tcp.c, tcp.h, tcppackets.c, tcppackets.h, + tcpprocess.c: initial file xfer support added- untested + +1999-04-29 Denis V. Dmitrienko <denis@null.net> + + * icqlib.h, udp.c, udp.h, udphandle.c: Unsuccessful attempt to + implement web presence (webaware) feature - doesn't seems to work + in ICQ v2. + + * list.c, tcp.c, tcplink.c, tcpprocess.c: Cleanups, warning + removed + + * Makefile.in, acinclude.m4, aclocal.m4, config.h.in, configure, + stamp-h.in, icqlib/Makefile.in: Removed automake/autoconf + generated tools from CVS - "make -f Makefile.cvs" to generate them + after checkout. + +1999-04-17 Bill Soudan <wes0472@rit.edu> + + reworked tcp system significantly- tcp links are now kept as a + seperate list instead of in icq_ContactItem. chat requests can now be + both sent and received successfully. + + * util.c, util.h, udphandle.c: removed *_link entries from + icq_ContactItem, including cleaup/init code + + * icqlib.c, icq.h: modified Send* functions to return DWORD + instead of WORD + + * tcp.c: _major_ restructuring. all tcp sockets (including + listening sockets) are kept in global linked list, icq_TCPLinks. + accept and listen functions moved to tcplink.c. changed return + values of Send* functions to DWORD. + + * tcp.h: changed return values of Send* functions to DWORD. + + * tcplink.c, tcplink.h: fixed bug in tcp_link_on_data_received, + multiple packets that come in on one recv call are now handled + correctly. added tcp_link_accept and tcp_link_listen. started + using mode and type structure entries. added icq_TCPLinks list + and find_tcp_link function. changed received_queue and send_queue + to lists. + + * tcppacket.c, tcppacket.h: added tcp_packet_node_delete function + and changed structure to include list_node for new list routines. + + * tcppackets.c, tcppackets.h: added new functions to create + chat packets. removed unnecessary code. added new function to + create URL ack packet. + + * tcpprocess.c: reworked code to use tcp_links instead of + icq_ContactItem entries. modified ProcessChatPacket to negotiate + both sending and receiving chat requests properly. + + * list.c, list.h: new list functions- replaces packetqueue + and handles new list of tcp_links + + * packetqueue.c, packetqueue.h: removed, list.c now used for + queues + + * Makefile.am: removed packetqueue.c, added list.c + +1999-04-14 Denis V. Dmitrienko <denis@null.net> + + * tcpprocess.c: icq_ContactItem parameter added to function + icq_TCPOnMessageReceived(). Segfault fixed on spoofed messages. + + * icqlib.c, proxy.c, packetqueue.c, icqlib.h, tcp.c, tcp.h, + tcplink.c, udp.c, udp.h, udphandle.c, util.c, util.h, tcppacket.c, + tcppackets.c, tcpprocess.c, tcppackets.h: Cleanups for "strict" + compiling (-ansi -pedantic) + + * icqlib.c, proxy.c, udp.c, udphandle.c, cyrillic.c: Switched from + icq_Log callback to icq_FmtLog function. + + * tcp.h: Some declarations added + + * tcp.c: Parameter port added to icq_TCPCreateListeningSocket() + function. + + * icq.h: Added icq_FmtLog() + + * configure: Added AC_CHECK_COMPILERS to allow --enable-debug and + --enable-strict configure options. + +1999-04-05 Bill Soudan <wes0472@rit.edu> + + icqlib will now create and listen on the chat socket when + necessary, and will perform negotiation for _receiving_ remote + chat requests only. + + * callbacks.c icq.h tcp.c tcp.h tcplink.c tcplink.h tcppacket.c + tcppackets.c tcppackets.h tcpprocess.c udphandle.c util.c + util.h: added initial chat support + +1999-04-05 Denis V. Dmitrienko <denis@null.net> + + * icqlib.c: Send messages and URLs to 'not in list' users fixed. + +1999-03-30 Bill Soudan <wes0472@rit.edu> + + tcp messages and urls completely functional! + unsuccessful connects not handled yet, however, plus connect + is currently blocking (yuck) + + * util.c: cleaned up old TCPLog function + * udphandle.c: added tcpflag handling to UserOnline + * icq.h: added icq_TCPSendURL and modified icq_UserOnline to + handle tcpflag + * icqlib.c: added tcp support to SendURL + * icqlib.h: modified LOGIN_X2_DEF to 0x04 instead of 0x06- we're + ready to accept tcp packets now! removed duplicate LOGIN_X* + definitions + * packetqueue.c tcp.c tcp.h tcplink.c tcppacket.c tcppackets.c + tcppackets.h tcpprocess.c: wrapped up many tcp details- code + now handles incoming and outgoing tcp messages and urls! + +1999-03-30 Vadim Zaliva <lorda@crocodile.org> + + * icqlib/util.c (icq_GetCountryName): function prototype now takes + 'unsigned short' as country code. + Country codes list now prorerly sorted, thus no need to sort it + using qsort. + +1999-03-29 Vadim Zaliva <lord@crocodile.org> + + * icqlib/util.c (icq_ConvertStatus2Str): this function now accepts + ulong as sttatus argument, since we use unsigned long for status + everywhere. + (icq_TCPXlateStatus): This function now use unsigned long as + 'udp_status' parameter type. + (icq_GetCountryName): Optimized country code search. + (icq_TCPXlateStatus): cleanup. + + * icqlib/icq.h: Change state constants to long. + +1999-03-27 Bill Soudan <wes0472@rit.edu> + + preliminary tcp support added and functional! + tcp messages will send to and from remote client when kicq + initiates the connection- remote clients will not try a tcp + connection to kicq yet + + * icq.h: added extern TCP function prototypes + * icqlib.c: added TCP support to icq_SendMessage + * packetqueue.c: cleaned up, fixed bugs, finished packet_queue_dump + * tcp.c: added icq_TCPSendMessage and socket close/process logic + * tcplink.c: fixed tcp_link_connect so it really connects to + remote client instead of always to my local test computer O:) + * tcppacket.c: added code to handle null string in + tcp_packet_append_string + * tcppackets.c,h: CreateStdPacket actually puts IP and port info + in now, added CreateStdAck and CreateMessageAck + * udphandle.c: fixed bug in HandleUserOnline (remote_ip and + remote_real_ip were not evaluating correctly), added hack + so I can test using local network, fixed function names + so icqlib compiles + * tcpprocess.c: added code to handle received messages, + finished process ack function + * util.c: removed static from Country_Codes so regwin.cpp + from kicq can use it + +1999-03-26 Bill Soudan <wes0472@rit.edu> + + * tcp.c, tcp.h: finished select logic + * tcplink.c: fixed C++ comments, cleaned up + * tcpprocess.c: added icq_TCPProcessHello + * packetqueue.c: moved packet_queue_find_queue from tcp.c + * util.c: rewrote icq_TCPLog + +1999-03-25 Bill Soudan <wes0472@rit.edu> + + * tcplink.c, tcplink.h: added + * Makefile.am: added tcplink.c + * icqlib.c: added #include "util.h" + * tcp.c, tcp.h: moved many functions into tcplink.c + * tcpprocess.c: changed types to standard + * udphandle.c: modified HandleUserOnline & Offline for new message_link + * util.c: ContItem functions modified for message_link + * util.h: message_link added to ContactItem struct, moved types to + seperate file + * icqtypes.h: added + * tcppacket.h: cleaned up + +1999-03-24 Denis V. Dmitrienko <denis@null.net> + + * Makefile.am, Makefile.in, callbacks.c, cyrillic.c, icq.h, + icqlib.c, icqlib.h, packetqueue.c, packetqueue.h, proxy.c, + proxy.h, tcp.c, tcp.h, tcppacket.c, tcppacket.h, tcppackets.c, + tcppackets.h, tcpprocess.c, udp.c, udp.h, udphandle.c, util.c, + util.h: + Underscored files with TCP stuff renamed. + TCP stuff cleaned up + Function names changed to corresponding names. + icqlib.c splitted to many small files by subject. + C++ comments changed to ANSI C comments. + + * Makefile.cvs, Makefile.in, acconfig.h, acinclude.m4, + acinclude.m4.in, aclocal.m4, config.guess, config.h.in, + config.sub, configure, configure.in, install-sh, libtool.m4.in, + ltconfig, ltmain.sh, mkinstalldirs, stamp-h.in: Updated + autoconf/automake/libtool configuration tools + +1999-03-22 Bill Soudan <wes0472@rit.edu> + + * Makefile.am: added new files + + * icqlib.h, icqlib.c: added additional struct entries in + icq_ContactItem for tcp code, added code in + icq_HandleUserOnline and icq_HandleUserOffline for setup/cleanup + + * added many files for tcp implementation: + icq_tcp.c icq_tcp.h icq_tcp_packets.c icq_tcp_packets.h + icq_tcp_process.c packet_queue.c packet_queue.h + tcp_packet.c tcp_packet.h util.c + +1999-03-05 Denis V. Dmitrienko <denis@null.net> + + * icqlib.h, icqlib.c, icq.h: Some cosmetic changes... + +Version 0.1.3 (08 Dec 1998) + SOCKS5 proxy support. + icq_RecvMessage now returns sending message time not receiving. + Visible list support changed. + Handle icq99a statuses. + +Version 0.1.2 (05 Oct 1998) + Search by UIN added. + SunOS port (Thanks to Joe Avila <joe@avilate.com>). + +Version 0.1.1 (21 Sep 1998) + Renamed from libicq to icqlib - there is another libicq on the net. + Little changes to allow UI call select() itself. + +Version 0.1.0 (18 Sep 1998) + Initial public version.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/INSTALL Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/Makefile.am Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,48 @@ +CFLAGS += -I\$(top_srcdir)/src +LIBS = $(GTK_LIBS) + +EXTRA_DIST = AUTHORS \ + COPYING \ + ChangeLog \ + INSTALL \ + README \ + VERSION + +pkgdir = $(libdir)/gaim +pkg_LTLIBRARIES = libgaimicq.la + +libgaimicq_la_SOURCES = chatsession.c \ + chatsession.h \ + contacts.c \ + contacts.h \ + cyrillic.c \ + filesession.c \ + filesession.h \ + icq.h \ + icqbyteorder.c \ + icqbyteorder.h \ + icqlib.c \ + icqlib.h \ + icqpacket.c \ + icqpacket.h \ + icqtypes.h \ + list.c \ + list.h \ + proxy.c \ + queue.c \ + queue.h \ + stdpackets.c \ + stdpackets.h \ + tcp.c \ + tcp.h \ + tcpchathandle.c \ + tcpfilehandle.c \ + tcphandle.c \ + tcplink.c \ + tcplink.h \ + udp.c \ + udp.h \ + udphandle.c \ + util.c \ + util.h \ + gaim_icq.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/Makefile.in Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,405 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AS = @AS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +DATADIRNAME = @DATADIRNAME@ +DLLTOOL = @DLLTOOL@ +ESD_CFLAGS = @ESD_CFLAGS@ +ESD_CONFIG = @ESD_CONFIG@ +ESD_LIBS = @ESD_LIBS@ +GENCAT = @GENCAT@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_CONFIG = @GLIB_CONFIG@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GNOMEGNORBA_LIBS = @GNOMEGNORBA_LIBS@ +GNOMEUI_LIBS = @GNOMEUI_LIBS@ +GNOME_APPLETS_LIBS = @GNOME_APPLETS_LIBS@ +GNOME_CAPPLET_LIBS = @GNOME_CAPPLET_LIBS@ +GNOME_CONFIG = @GNOME_CONFIG@ +GNOME_INCLUDEDIR = @GNOME_INCLUDEDIR@ +GNOME_LIBDIR = @GNOME_LIBDIR@ +GNOME_LIBS = @GNOME_LIBS@ +GNORBA_CFLAGS = @GNORBA_CFLAGS@ +GNORBA_LIBS = @GNORBA_LIBS@ +GTKXMHTML_LIBS = @GTKXMHTML_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_CONFIG = @GTK_CONFIG@ +GTK_LIBS = @GTK_LIBS@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LDADD = @LDADD@ +LIBOBJS = @LIBOBJS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +OBJDUMP = @OBJDUMP@ +ORBIT_CFLAGS = @ORBIT_CFLAGS@ +ORBIT_CONFIG = @ORBIT_CONFIG@ +ORBIT_IDL = @ORBIT_IDL@ +ORBIT_LIBS = @ORBIT_LIBS@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PTHREAD_LIB = @PTHREAD_LIB@ +RANLIB = @RANLIB@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XPM_LIBS = @XPM_LIBS@ +ZVT_LIBS = @ZVT_LIBS@ +gaimpath = @gaimpath@ +gnomepath = @gnomepath@ +l = @l@ +perlpath = @perlpath@ +sedpath = @sedpath@ + +CFLAGS = @CFLAGS@ -I\$(top_srcdir)/src +LIBS = $(GTK_LIBS) + +EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README VERSION + + +pkgdir = $(libdir)/gaim +pkg_LTLIBRARIES = libgaimicq.la + +libgaimicq_la_SOURCES = chatsession.c chatsession.h contacts.c contacts.h cyrillic.c filesession.c filesession.h icq.h icqbyteorder.c icqbyteorder.h icqlib.c icqlib.h icqpacket.c icqpacket.h icqtypes.h list.c list.h proxy.c queue.c queue.h stdpackets.c stdpackets.h tcp.c tcp.h tcpchathandle.c tcpfilehandle.c tcphandle.c tcplink.c tcplink.h udp.c udp.h udphandle.c util.c util.h gaim_icq.c + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(pkg_LTLIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +libgaimicq_la_LDFLAGS = +libgaimicq_la_LIBADD = +libgaimicq_la_OBJECTS = chatsession.lo contacts.lo cyrillic.lo \ +filesession.lo icqbyteorder.lo icqlib.lo icqpacket.lo list.lo proxy.lo \ +queue.lo stdpackets.lo tcp.lo tcpchathandle.lo tcpfilehandle.lo \ +tcphandle.lo tcplink.lo udp.lo udphandle.lo util.lo gaim_icq.lo +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ +Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +DEP_FILES = .deps/chatsession.P .deps/contacts.P .deps/cyrillic.P \ +.deps/filesession.P .deps/gaim_icq.P .deps/icqbyteorder.P \ +.deps/icqlib.P .deps/icqpacket.P .deps/list.P .deps/proxy.P \ +.deps/queue.P .deps/stdpackets.P .deps/tcp.P .deps/tcpchathandle.P \ +.deps/tcpfilehandle.P .deps/tcphandle.P .deps/tcplink.P .deps/udp.P \ +.deps/udphandle.P .deps/util.P +SOURCES = $(libgaimicq_la_SOURCES) +OBJECTS = $(libgaimicq_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/icq/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-pkgLTLIBRARIES: + +clean-pkgLTLIBRARIES: + -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES) + +distclean-pkgLTLIBRARIES: + +maintainer-clean-pkgLTLIBRARIES: + +install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(pkgdir) + @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkgdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL) $$p $(DESTDIR)$(pkgdir)/$$p; \ + else :; fi; \ + done + +uninstall-pkgLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(pkg_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(pkgdir)/$$p; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libgaimicq.la: $(libgaimicq_la_OBJECTS) $(libgaimicq_la_DEPENDENCIES) + $(LINK) -rpath $(pkgdir) $(libgaimicq_la_LDFLAGS) $(libgaimicq_la_OBJECTS) $(libgaimicq_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = plugins/icq + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu plugins/icq/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + +DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :) + +-include $(DEP_FILES) + +mostlyclean-depend: + +clean-depend: + +distclean-depend: + -rm -rf .deps + +maintainer-clean-depend: + +%.o: %.c + @echo '$(COMPILE) -c $<'; \ + $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-cp .deps/$(*F).pp .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm .deps/$(*F).pp + +%.lo: %.c + @echo '$(LTCOMPILE) -c $<'; \ + $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $< + @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \ + < .deps/$(*F).pp > .deps/$(*F).P; \ + tr ' ' '\012' < .deps/$(*F).pp \ + | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \ + >> .deps/$(*F).P; \ + rm -f .deps/$(*F).pp +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: install-pkgLTLIBRARIES +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-pkgLTLIBRARIES +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(pkgdir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-pkgLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags mostlyclean-depend \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-pkgLTLIBRARIES clean-compile clean-libtool clean-tags \ + clean-depend clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-pkgLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-depend \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-pkgLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-depend \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-pkgLTLIBRARIES distclean-pkgLTLIBRARIES \ +clean-pkgLTLIBRARIES maintainer-clean-pkgLTLIBRARIES \ +uninstall-pkgLTLIBRARIES install-pkgLTLIBRARIES mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir mostlyclean-depend \ +distclean-depend clean-depend maintainer-clean-depend info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/README Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,85 @@ +icqlib v1.0.0 +Denis V. Dmitrienko <denis@null.net> +Bill Soudan <soudan@kde.org> + +DESCRIPTION +----------- +icqlib is the most feature complete, open source, library implementation +of Mirabilis' ICQ protocol available on the Internet. icqlib currently +supports approximately 90% of the ICQ UDP v5 protocol and 80% of the +ICQ TCP v2 protocol, including new UIN registration, chat, and file +transfer. + +Features: +* written in C for portability - compiles on most Unices +* supports multiple simultaneous connections to ICQ servers - more + than one UIN can log in and receive events +* SOCKS5 firewall support for both UDP and TCP protocols +* event driven, non-blocking interface +* supports Russian language - automatically performs conversion from + Windows 1251 encoding to unix koi8 encoding + +DOWNLOAD +-------- +Home page: + http://kicq.sourceforge.net/icqlib.shtml +Direct download: + http://download.sourceforge.net/icqlib/icqlib-1.0.0.tar.gz + ftp://ftp.kde.org/pub/kde/unstable/apps/network/icqlib-1.0.0.tar.gz + +INSTALL +------- +This is very basic: + ./configure + make + su -c "make install" + +If you want to install in other place: + ./configure --prefix=/place/to/install/icqlib + make + make install + +You should have permissions to write in /place/to/install/icqlib or should +install it from root: + su -c "make install" + +For more details read INSTALL file. + +BUGS +---- +If you find one that isn't listed, submit your bugreport here: +http://sourceforge.net/bugs/?group_id=384 +And if you have a fix for it, so much the better! Submit your patch +here: +http://sourceforge.net/patch/?group_id=384 + +PARTICIPATION +------------- +You can participate in icqlib project in any way here: +http://sourceforge.net/projects/icqlib +Send your feature requests here: +http://sourceforge.net/support/?group_id=384 + +Please try to avoid abusing developers with direct email messages, +especially if your question could be already answered somewhere in +the project forums or mailing lists. Please use provided above web +forms to submit your reports and requests. And of course, any kind of +contributions and propositions are very appreciated and welcomed, and +could be sent directly. Thank you for your understanding and patience. + +THANKS +------ +To +- Matthew Smith, Magnus Ihse, Jeremy Wise, Henrik Isaksson and other + people from ICQDev <icq-devel@lists.realminfo.com> and + micq <micq@phantom.iquest.net> mailing lists for their contribution + in icq protocol research +- K Desktop Environment developers +- icqlib and kicq users + +And finally +- Linus Torvalds, Alan Cox and other Linux programmers for great OS + +-- +Enjoy! +icqlib development team.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/VERSION Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,1 @@ +1.0.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/chatsession.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,52 @@ + +#include <stdlib.h> + +#include "chatsession.h" +#include "list.h" + +icq_ChatSession *icq_ChatSessionNew(ICQLINK *icqlink) +{ + icq_ChatSession *p=(icq_ChatSession *)malloc(sizeof(icq_ChatSession)); + + if (p) + { + p->remote_handle=0L; + p->status=0; + p->id=0L; + p->icqlink=icqlink; + list_insert(icqlink->icq_ChatSessions, 0, p); + } + + return p; +} + +void icq_ChatSessionDelete(void *p) +{ + free(p); +} + +void icq_ChatSessionClose(icq_ChatSession *p) +{ + list_remove(p->icqlink->icq_ChatSessions, p); + icq_ChatSessionDelete(p); +} + +int _icq_FindChatSession(void *p, va_list data) +{ + DWORD uin=va_arg(data, DWORD); + return (((icq_ChatSession *)p)->remote_uin == uin); +} + +icq_ChatSession *icq_FindChatSession(ICQLINK *icqlink, DWORD uin) +{ + return list_traverse(icqlink->icq_ChatSessions, + _icq_FindChatSession, uin); +} + +void icq_ChatSessionSetStatus(icq_ChatSession *p, int status) +{ + p->status=status; + if(p->id) + if(p->icqlink->icq_RequestNotify) + (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_CHAT, status, 0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/chatsession.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,80 @@ + +#ifndef _CHAT_SESSION_H +#define _CHAT_SESSION_H + +#include "icq.h" +#include "icqtypes.h" + +/* chat session statuses- request receiver */ +#define CHAT_STATUS_LISTENING 1 +#define CHAT_STATUS_CONNECTED 3 +#define CHAT_STATUS_WAIT_NAME 4 +#define CHAT_STATUS_WAIT_FONT 6 + +/* chat session statuses- request sender */ +#define CHAT_STATUS_CONNECTING 2 +#define CHAT_STATUS_WAIT_ALLINFO 5 + +/* once negotiation is complete, both sides enter ready state */ +#define CHAT_STATUS_READY 7 + +/* chat session states: + + accepting chat request + + 1. remote user initiates chat by sending chat request to message listen + port + 2. local user accepts chat, ack packet sent back to remote user and + chat listen port opened + * chat session created on local side with ID of ack packet + LISTENING + * remote chat session created with ID of ack packet + CONNECTING + 3. remote client connects to local chat listen port, sends hello and + sends info packet with name and colors + * local chat session associated with new icq_TCPLink according to uin + 4. local client sends back big info packet with name, colors, and font + + 5. remote client sends font packet, connection is considered established + + sending chat request + + 1. local user initiates chat by sending chat request to remote message + listen port + 2. remote user accepts chat, ack packet received from remote client and + remote client opens chat listen port + 3. local client connects to remote chat listen port, sends hello and + sends info packet with name and colors + 4. remote client sends back big info packet with name, colors, and font + 5. local client sends font packet, connection is considered established + + 1. icq_RecvChatRequest - provides session ID (same as packet sequence) + 2. icq_SendChatAck - pass session ID + ICQ_NOTIFY_CONNECTED + ICQ_NOTIFY_SENT + ICQ_NOTIFY_CHAT, CHAT_STATUS_LISTENING + 3. ICQ_NOTIFY_CHAT, CHAT_STATUS_WAIT_NAME + 4. ICQ_NOTIFY_CHAT, CHAT_STATUS_WAIT_FONT + 5. ICQ_NOTIFY_CHAT, CHAT_STATUS_CONNECTED + ICQ_NOTIFY_CHATDATA, .... + ICQ_NOTIFY_SUCCESS +*/ + +typedef struct icq_ChatSession_s { + + DWORD id; + int status; + ICQLINK *icqlink; + + DWORD remote_uin; + char *remote_handle; + +} icq_ChatSession; + +icq_ChatSession *icq_ChatSessionNew(ICQLINK *); +void icq_ChatSessionDelete(void *); +void icq_ChatSessionClose(icq_ChatSession *); +void icq_ChatSessionSetStatus(icq_ChatSession *, int); +icq_ChatSession *icq_FindChatSession(ICQLINK *, DWORD); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/contacts.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: contacts.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.4 2000/06/17 16:38:45 denis +New parameter was added in icq_ContactSetVis() for setting/resetting +'Visible to User' status. +Port's type was changed to unsigned short in icq_UserOnline callback. + +Revision 1.3 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.2 1999/07/23 12:28:00 denis +Cleaned up. + +Revision 1.1 1999/07/18 20:11:48 bills +added + +*/ + +#include <stdlib.h> +#include <stdarg.h> + +#include "icqtypes.h" +#include "util.h" +#include "icq.h" +#include "list.h" +#include "contacts.h" + +icq_ContactItem *icq_ContactNew(ICQLINK *link) +{ + icq_ContactItem *pcontact= + (icq_ContactItem *)malloc(sizeof(icq_ContactItem)); + + if(pcontact) + pcontact->icqlink=link; + + return pcontact; +} + +void icq_ContactDelete(void *p) +{ + free(p); +} + +void icq_ContactAdd(ICQLINK *link, DWORD cuin) +{ + icq_ContactItem *p = icq_ContactNew(link); + p->uin = cuin; + p->vis_list = FALSE; + + list_enqueue(link->icq_ContactList, p); +} + +void icq_ContactRemove(ICQLINK *link, DWORD cuin) +{ + icq_ContactItem *pcontact=icq_ContactFind(link, cuin); + + if (pcontact) + { + list_remove(link->icq_ContactList, pcontact); + icq_ContactDelete(pcontact); + } +} + +void icq_ContactClear(ICQLINK *link) +{ + list_delete(link->icq_ContactList, icq_ContactDelete); + link->icq_ContactList=list_new(); +} + +int _icq_ContactFind(void *p, va_list data) +{ + DWORD uin=va_arg(data, DWORD); + + return (((icq_ContactItem *)p)->uin == uin); +} + +icq_ContactItem *icq_ContactFind(ICQLINK *link, DWORD cuin) +{ + return list_traverse(link->icq_ContactList, _icq_ContactFind, cuin); +} + +void icq_ContactSetVis(ICQLINK *link, DWORD cuin, BYTE vu) +{ + icq_ContactItem *p = icq_ContactFind(link, cuin); + if(p) + p->vis_list = vu; +} + +icq_ContactItem *icq_ContactGetFirst(ICQLINK *link) +{ + return list_first(link->icq_ContactList); +} + +icq_ContactItem *icq_ContactGetNext(icq_ContactItem *pcontact) +{ + list_node *p=list_find(pcontact->icqlink->icq_ContactList, pcontact); + + if (p && p->next) + return p->next->item; + else + return 0L; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/contacts.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,25 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _CONTACTS_H +#define _CONTACTS_H + +#include "icq.h" +#include "icqtypes.h" + +typedef struct icq_ContItem +{ + ICQLINK *icqlink; + unsigned long uin; + int vis_list; + unsigned long remote_ip; + unsigned long remote_real_ip; + unsigned long remote_port; + unsigned char tcp_flag; +} icq_ContactItem; + +icq_ContactItem *icq_ContactNew(ICQLINK *link); +void icq_ContactDelete(void *pcontact); +icq_ContactItem *icq_ContactFind(ICQLINK *link, DWORD cuin); +icq_ContactItem *icq_ContactGetFirst(ICQLINK *link); +icq_ContactItem *icq_ContactGetNext(icq_ContactItem *pcontact); + +#endif /* _CONTACTS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/cyrillic.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,138 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: cyrillic.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.7 2000/05/21 17:41:14 denis +Applied patch for russian letters IO and io by +Vladimir Eltchinov <elik@design.ru> + +Revision 1.6 2000/02/07 02:31:37 bills +added icq_RusConv_n + +Revision 1.5 1999/09/29 16:45:26 denis +Cleanups + +Revision 1.4 1999/07/16 12:08:20 denis +Cleaned up. + +Revision 1.3 1999/07/12 15:13:29 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.2 1999/04/14 14:44:30 denis +Switched from icq_Log callback to icq_FmtLog function. + +Revision 1.1 1999/03/24 11:37:35 denis +Underscored files with TCP stuff renamed. +TCP stuff cleaned up +Function names changed to corresponding names. +icqlib.c splitted to many small files by subject. +C++ comments changed to ANSI C comments. + +*/ + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "util.h" + +BYTE kw[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,168,180,181,182,183,184,185,186,187,188,189,190,191, + 254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238, + 239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250, + 222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206, + 207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218}; + +BYTE wk[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,179,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,163,185,186,187,188,189,190,191, + 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240, + 242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241, + 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208, + 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209}; + +/******************************************************** +Russian language ICQ fix. +Usual Windows ICQ users do use Windows 1251 encoding but +unix users do use koi8 encoding, so we need to convert it. +This function will convert string from windows 1251 to koi8 +or from koi8 to windows 1251. +Andrew Frolov dron@ilm.net +*********************************************************/ + +extern int icq_Russian; + +void icq_RusConv(const char to[4], char *t_in) +{ + BYTE *table; + int i; + +/* 6-17-1998 by Linux_Dude + * Moved initialization of table out front of 'if' block to prevent compiler + * warning. Improved error message, and now return without performing string + * conversion to prevent addressing memory out of range (table pointer would + * previously have remained uninitialized (= bad)). + */ + + table = wk; + if(strcmp(to, "kw") == 0) + table = kw; + else if(strcmp(to, "wk") != 0) + { + icq_FmtLog(NULL, ICQ_LOG_ERROR, "Unknown option in call to Russian Convert\n"); + return; + } + +/* End Linux_Dude's changes ;) */ + + if(icq_Russian) + { + for(i=0;t_in[i]!=0;i++) + { + t_in[i] &= 0377; + if(t_in[i] & 0200) + t_in[i] = table[t_in[i] & 0177]; + } + } +} + +void icq_RusConv_n(const char to[4], char *t_in, int len) +{ + BYTE *table; + int i; + +/* 6-17-1998 by Linux_Dude + * Moved initialization of table out front of 'if' block to prevent compiler + * warning. Improved error message, and now return without performing string + * conversion to prevent addressing memory out of range (table pointer would + * previously have remained uninitialized (= bad)). + */ + + table = wk; + if(strcmp(to, "kw") == 0) + table = kw; + else if(strcmp(to, "wk") != 0) + { + icq_FmtLog(NULL, ICQ_LOG_ERROR, "Unknown option in call to Russian Convert\n"); + return; + } + +/* End Linux_Dude's changes ;) */ + + if(icq_Russian) + { + for(i=0;i < len;i++) + { + t_in[i] &= 0377; + if(t_in[i] & 0200) + t_in[i] = table[t_in[i] & 0177]; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/filesession.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,233 @@ +#include <stdlib.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> + +#ifdef _MSVC_ +#include <io.h> +#define open _open +#define close _close +#define read _read +#define write _write +#endif + +#include "filesession.h" +#include "list.h" +#include "icqpacket.h" +#include "stdpackets.h" + +icq_FileSession *icq_FileSessionNew(ICQLINK *icqlink) +{ + icq_FileSession *p=(icq_FileSession *)malloc(sizeof(icq_FileSession)); + + if (p) + { + p->status=0; + p->id=0L; + p->icqlink=icqlink; + p->current_fd=-1; + p->current_file_num=0; + p->current_file_progress=0; + p->current_file_size=0; + p->files=0L; + p->current_speed=100; + p->total_bytes=0; + p->total_files=0; + p->total_transferred_bytes=0; + p->working_dir[0]=0; + list_insert(icqlink->icq_FileSessions, 0, p); + } + + return p; +} + +void icq_FileSessionDelete(void *pv) +{ + icq_FileSession *p=(icq_FileSession *)pv; + + if(p->files) { + char **p2=p->files; + while(*p2) + free(*(p2++)); + free(p->files); + } + + if (p->current_fd > -1 ) { + close(p->current_fd); + p->current_fd=-1; + } + + free(p); +} + +int _icq_FindFileSession(void *p, va_list data) +{ + icq_FileSession *psession=(icq_FileSession *)p; + DWORD uin=va_arg(data, DWORD); + unsigned long id=va_arg(data, unsigned long); + + return (psession->remote_uin == uin) && ( id ? (psession->id == id) : 1 ); + +} + +icq_FileSession *icq_FindFileSession(ICQLINK *icqlink, DWORD uin, + unsigned long id) +{ + return list_traverse(icqlink->icq_FileSessions, _icq_FindFileSession, + uin, id); +} + +void icq_FileSessionSetStatus(icq_FileSession *p, int status) +{ + if(status!=p->status) + { + p->status=status; + if(p->id && p->icqlink->icq_RequestNotify) + (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_FILE, + status, 0); + } +} + +void icq_FileSessionSetHandle(icq_FileSession *p, const char *handle) +{ + strncpy(p->remote_handle, handle, 64); +} + +void icq_FileSessionSetCurrentFile(icq_FileSession *p, const char *filename) +{ + struct stat file_status; + char file[1024]; + + strcpy(file, p->working_dir); + strcat(file, filename); + + if (p->current_fd>-1) { + close(p->current_fd); + p->current_fd=-1; + } + + strncpy(p->current_file, file, 64); + p->current_file_progress=0; + + /* does the file already exist? */ + if (stat(file, &file_status)==0) { + p->current_file_progress=file_status.st_size; + p->total_transferred_bytes+=file_status.st_size; + p->current_fd=open(file, O_WRONLY | O_APPEND); + } else { +#ifdef _WIN32 + p->current_fd=open(file, O_WRONLY | O_CREAT); +#else + p->current_fd=open(file, O_WRONLY | O_CREAT, S_IRWXU); +#endif + } + + /* make sure we have a valid filehandle */ + if (p->current_fd == -1) + perror("couldn't open file: "); + +} + +void icq_FileSessionPrepareNextFile(icq_FileSession *p) +{ + int i=0; + char **files=p->files; + + p->current_file_num++; + + while(*files) { + i++; + if(i==p->current_file_num) + break; + else + files++; + } + + if(*files) { + struct stat file_status; + + if (p->current_fd>-1) { + close(p->current_fd); + p->current_fd=-1; + } + + if (stat(*files, &file_status)==0) { + char *basename=*files; + char *pos=strrchr(basename, '/'); + if(pos) basename=pos+1; + strncpy(p->current_file, basename, 64); + p->current_file_progress=0; + p->current_file_size=file_status.st_size; + p->current_fd=open(*files, O_RDONLY); + } + + /* make sure we have a valid filehandle */ + if (p->current_fd == -1) + perror("couldn't open file: "); + } +} + +void icq_FileSessionSendData(icq_FileSession *p) +{ + /* for now just send a packet at a time */ + char buffer[2048]; + int count=read(p->current_fd, buffer, 2048); + + if(count>0) { + icq_Packet *p2=icq_TCPCreateFile06Packet(count, buffer); + icq_TCPLinkSend(p->tcplink, p2); + p->total_transferred_bytes+=count; + p->current_file_progress+=count; + icq_FileSessionSetStatus(p, FILE_STATUS_SENDING); + + if (p->icqlink->icq_RequestNotify) + (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, + ICQ_NOTIFY_FILEDATA, count, NULL); + } + + /* done transmitting if read returns less that 2048 bytes */ + if(count<2048) + icq_FileSessionClose(p); + + return; +} + +/* public */ + +void icq_FileSessionSetSpeed(icq_FileSession *p, int speed) +{ + icq_Packet *packet=icq_TCPCreateFile05Packet(speed); + + icq_TCPLinkSend(p->tcplink, packet); +} + +void icq_FileSessionClose(icq_FileSession *p) +{ + icq_TCPLink *plink=p->tcplink; + + /* TODO: handle closing already unallocated filesession? */ + + /* if we're attached to a tcplink, unattach so the link doesn't try + * to close us, and then close the tcplink */ + if (plink) + { + plink->session=0L; + icq_TCPLinkClose(plink); + } + + icq_FileSessionDelete(p); + + list_remove(p->icqlink->icq_FileSessions, p); +} + +void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir) +{ + strncpy(p->working_dir, dir, 512); +} + +void icq_FileSessionSetFiles(icq_FileSession *p, char **files) +{ + p->files=files; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/filesession.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,17 @@ + +#ifndef _FILE_SESSION_H +#define _FILE_SESSION_H + +#include "icq.h" +#include "icqtypes.h" + +icq_FileSession *icq_FileSessionNew(ICQLINK *); +void icq_FileSessionDelete(void *); +void icq_FileSessionSetStatus(icq_FileSession *, int); +icq_FileSession *icq_FindFileSession(ICQLINK *, unsigned long, unsigned long); +void icq_FileSessionSetHandle(icq_FileSession *, const char *); +void icq_FileSessionSetCurrentFile(icq_FileSession *, const char *); +void icq_FileSessionPrepareNextFile(icq_FileSession *); +void icq_FileSessionSendData(icq_FileSession *); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/gaim_icq.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,292 @@ +#include <gtk/gtk.h> +#include "icq.h" /* well, we're doing ICQ, right? */ +#include "multi.h" /* needed for gaim_connection */ +#include "prpl.h" /* needed for prpl */ +#include "gaim.h" /* needed for every other damn thing */ + +struct icq_data { + ICQLINK *link; + int cur_status; + int tcp_timer; + int ack_timer; +}; + +static struct gaim_connection *find_gaim_conn_by_icq_link(ICQLINK *link) { + GSList *c = connections; + struct gaim_connection *gc = NULL; + struct icq_data *id; + + while (c) { + gc = (struct gaim_connection *)c->data; + if (gc->protocol == PROTO_ICQ) { + id = (struct icq_data *)gc->proto_data; + if (id->link == link) + break; + } + gc = NULL; + c = c->next; + } + + return gc; +} + +static char *icq_name() { + return "ICQ"; +} + +static void icq_do_log(ICQLINK *link, time_t time, unsigned char level, const char *log) { + debug_printf("ICQ debug %d: %s", level, log); +} + +static gint icq_tcp_timer(ICQLINK *link) { + icq_TCPMain(link); + return TRUE; +} + +static void icq_callback(gpointer data, gint source, GdkInputCondition condition) { + struct gaim_connection *gc = (struct gaim_connection *)data; + struct icq_data *id = (struct icq_data *)gc->proto_data; + debug_printf("ICQ Callback handler\n"); + + icq_HandleServerResponse(id->link); +} + +static void icq_online(ICQLINK *link) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + struct icq_data *id = (struct icq_data *)gc->proto_data; + debug_printf("%s is now online.\n", gc->username); + account_online(gc); + serv_finish_login(gc); + + if (bud_list_cache_exists(gc)) + do_import(NULL, gc); + + icq_ChangeStatus(id->link, STATUS_ONLINE); +} + +static void icq_logged_off(ICQLINK *link) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + struct icq_data *id = (struct icq_data *)gc->proto_data; + int icqSocket; + + gtk_timeout_remove(id->tcp_timer); + gdk_input_remove(gc->inpa); + + if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) { + hide_login_progress(gc, "Unable to connect"); + g_free(id); + signoff(gc); + return; + } + + icqSocket = icq_GetSok(link); + gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc); + + icq_Login(link, STATUS_ONLINE); + id->cur_status = STATUS_ONLINE; + + id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link); +} + +static void icq_msg_incoming(ICQLINK *link, unsigned long uin, unsigned char hour, unsigned char minute, + unsigned char day, unsigned char month, unsigned short year, const char *data) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + char buf[256], *tmp = g_strdup(data); + g_snprintf(buf, sizeof buf, "%lu", uin); + serv_got_im(gc, buf, tmp, 0); + g_free(tmp); +} + +static void icq_user_online(ICQLINK *link, unsigned long uin, unsigned long status, + unsigned long ip, unsigned short port, unsigned long real_ip, + unsigned char tcp_flags) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin); + serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0); +} + +static void icq_user_offline(ICQLINK *link, unsigned long uin) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin); + serv_got_update(gc, buf, 0, 0, 0, 0, 0, 0); +} + +static void icq_user_status(ICQLINK *link, unsigned long uin, unsigned long status) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin); + serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0); +} + +static gint icq_set_timeout_cb(struct icq_data *id) { + icq_HandleTimeout(id->link); + id->ack_timer = -1; + return FALSE; +} + +static void icq_set_timeout(ICQLINK *link, long interval) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + struct icq_data *id = (struct icq_data *)gc->proto_data; + + debug_printf("icq_SetTimeout: %ld\n", interval); + if (interval > 0 && id->ack_timer < 1) + id->ack_timer = gtk_timeout_add(interval * 1000, (GtkFunction)icq_set_timeout_cb, id); + else if (id->ack_timer > 0) { + gtk_timeout_remove(id->ack_timer); + id->ack_timer = -1; + } +} + +static void icq_url_incoming(struct icq_link *link, unsigned long uin, unsigned char hour, + unsigned char minute, unsigned char day, unsigned char month, + unsigned short year, const char *url, const char *descr) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + int len = strlen(url) + strlen(descr) + 25; /* 25 is straight out of my ass */ + char *msg = g_malloc(len), buf[256]; + g_snprintf(msg, len, "<A HREF=\"%s\">%s</A>", url, descr); + g_snprintf(buf, 256, "%lu", uin); + serv_got_im(gc, buf, msg, 0); + g_free(msg); +} + +static void icq_wrong_passwd(struct icq_link *link) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + hide_login_progress(gc, "Invalid password."); + signoff(gc); +} + +static void icq_invalid_uin(struct icq_link *link) { + struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); + hide_login_progress(gc, "Invalid UIN."); + signoff(gc); +} + +static void icq_login(struct aim_user *user) { + struct gaim_connection *gc = new_gaim_conn(user); + struct icq_data *id = gc->proto_data = g_new0(struct icq_data, 1); + ICQLINK *link = id->link = g_new0(ICQLINK, 1); + int icqSocket; + + icq_LogLevel = ICQ_LOG_MESSAGE; + + icq_Init(link, atol(user->username), user->password, "gaim user" /* hehe :) */); + + link->icq_Logged = icq_online; + link->icq_Disconnected = icq_logged_off; + link->icq_RecvMessage = icq_msg_incoming; + link->icq_RecvURL = icq_url_incoming; + link->icq_UserOnline = icq_user_online; + link->icq_UserOffline = icq_user_offline; + link->icq_UserStatusUpdate = icq_user_status; + link->icq_WrongPassword = icq_wrong_passwd; + link->icq_InvalidUIN = icq_invalid_uin; + link->icq_Log = icq_do_log; + link->icq_SetTimeout = icq_set_timeout; + + icq_UnsetProxy(link); + + if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) { + hide_login_progress(gc, "Unable to connect"); + g_free(id); + signoff(gc); + return; + } + + icqSocket = icq_GetSok(link); + gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc); + + icq_Login(link, STATUS_ONLINE); + id->cur_status = STATUS_ONLINE; + + id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link); + + set_login_progress(gc, 0, "Connecting..."); +} + +static void icq_close(struct gaim_connection *gc) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + + gtk_timeout_remove(id->tcp_timer); + gdk_input_remove(gc->inpa); + icq_Logout(id->link); + icq_Disconnect(id->link); + icq_Done(id->link); + g_free(id->link); +} + +static struct prpl *my_protocol = NULL; + +static void icq_send_msg(struct gaim_connection *gc, char *who, char *msg, int away) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + icq_SendMessage(id->link, atol(who), msg, !away); +} + +static void icq_keepalive(struct gaim_connection *gc) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + icq_KeepAlive(id->link); +} + +static void icq_add_buddy(struct gaim_connection *gc, char *who) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + icq_ContactAdd(id->link, atol(who)); + icq_ContactSetVis(id->link, atol(who), TRUE); + icq_SendNewUser(id->link, atol(who)); +} + +static void icq_add_buddies(struct gaim_connection *gc, GList *whos) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + while (whos) { + icq_ContactAdd(id->link, atol(whos->data)); + icq_ContactSetVis(id->link, atol(whos->data), TRUE); + icq_SendNewUser(id->link, atol(whos->data)); + whos = whos->next; + } +} + +static void icq_rem_buddy(struct gaim_connection *gc, char *who) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + icq_ContactRemove(id->link, atol(who)); +} + +static void icq_set_away(struct gaim_connection *gc, char *msg) { + struct icq_data *id = (struct icq_data *)gc->proto_data; + + if (msg && msg[0]) { + icq_ChangeStatus(id->link, STATUS_NA); + } else { + icq_ChangeStatus(id->link, STATUS_ONLINE); + } +} + +static void icq_init(struct prpl *ret) { + ret->protocol = PROTO_ICQ; + ret->name = icq_name; + ret->login = icq_login; + ret->close = icq_close; + ret->send_im = icq_send_msg; + ret->add_buddy = icq_add_buddy; + ret->add_buddies = icq_add_buddies; + ret->remove_buddy = icq_rem_buddy; + ret->set_away = icq_set_away; + ret->keepalive = icq_keepalive; + + my_protocol = ret; +} + +char *gaim_plugin_init(GModule *handle) { + load_protocol(icq_init); + return NULL; +} + +void gaim_plugin_remove() { + struct prpl *p = find_prpl(PROTO_ICQ); + if (p == my_protocol) + unload_protocol(p); +} + +char *name() { + return "ICQ"; +} + +char *description() { + return "Allows gaim to use the ICQ protocol"; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icq.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,368 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _ICQ_H_ +#define _ICQ_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define ICQLIBVER 0x010000 +#define ICQLIBMAJOR 1 +#define ICQLIBMINOR 0 +#define ICQLIBMICRO 0 + +#include <time.h> + +#ifndef _WIN32 +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#endif + +#ifdef _WIN32 +#include <winsock.h> +#endif + +#define ICQ_LOG_OFF 0 +#define ICQ_LOG_FATAL 1 +#define ICQ_LOG_ERROR 2 +#define ICQ_LOG_WARNING 3 +#define ICQ_LOG_MESSAGE 4 + +#define STATUS_OFFLINE (-1L) +#define STATUS_ONLINE 0x0000L +#define STATUS_AWAY 0x0001L +#define STATUS_DND 0x0002L /* 0x13L */ +#define STATUS_NA 0x0004L /* 0x05L */ +#define STATUS_OCCUPIED 0x0010L /* 0x11L */ +#define STATUS_FREE_CHAT 0x0020L +#define STATUS_INVISIBLE 0x0100L + +#define ICQ_SEND_THRUSERVER 0 +#define ICQ_SEND_DIRECT 1 +#define ICQ_SEND_BESTWAY 2 + +#define ICQ_NOTIFY_SUCCESS 0 +#define ICQ_NOTIFY_FAILED 1 +#define ICQ_NOTIFY_CONNECTING 2 +#define ICQ_NOTIFY_CONNECTED 3 +#define ICQ_NOTIFY_SENT 4 +#define ICQ_NOTIFY_ACK 5 + +#define ICQ_NOTIFY_CHAT 6 +#define ICQ_NOTIFY_CHATDATA 7 + +#define ICQ_NOTIFY_FILE 10 +#define ICQ_NOTIFY_FILESESSION 11 +#define ICQ_NOTIFY_FILEDATA 12 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct +{ + const char *name; + unsigned short code; +} icq_ArrayType; + +typedef struct icq_link +{ + /* General */ + unsigned long icq_Uin; + unsigned long icq_OurIP; /* HOST byteorder */ + unsigned short icq_OurPort; /* HOST byteorder */ + void *icq_ContactList; + unsigned long icq_Status; + char *icq_Password; + char *icq_Nick; + + /* UDP stuff */ + int icq_UDPSok; + unsigned char icq_UDPServMess[8192]; /* 65536 seqs max, 1 bit per seq -> 65536/8 = 8192 */ + unsigned short icq_UDPSeqNum1, icq_UDPSeqNum2; + unsigned long icq_UDPSession; + void *icq_UDPQueue; + int icq_UDPExpireInterval; + + /* TCP stuff */ + unsigned short icq_TCPSrvPort; /* HOST byteorder */ + int icq_TCPSequence; + void *icq_TCPLinks; + void *icq_ChatSessions; + void *icq_FileSessions; + int TCP_maxfd; + fd_set TCP_readfds; + fd_set TCP_writefds; + + /* SOCKS5 Proxy stuff */ + unsigned char icq_UseProxy; + char *icq_ProxyHost; + unsigned long icq_ProxyIP; /* HOST byteorder */ + unsigned short icq_ProxyPort; /* HOST byteorder */ + int icq_ProxyAuth; + char *icq_ProxyName; + char *icq_ProxyPass; + int icq_ProxySok; + unsigned short icq_ProxyOurPort; /* HOST byteorder */ + unsigned long icq_ProxyDestIP; /* HOST byteorder */ + unsigned short icq_ProxyDestPort; /* HOST byteorder */ + + /*** Callbacks ***/ + void (*icq_Logged)(struct icq_link *link); + void (*icq_Disconnected)(struct icq_link *link); + void (*icq_RecvMessage)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *msg); + void (*icq_RecvURL)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *url, + const char *descr); + void (*icq_RecvWebPager)(struct icq_link *link,unsigned char hour, + unsigned char minute, unsigned char day, unsigned char month, + unsigned short year, const char *nick, const char *email, + const char *msg); + void (*icq_RecvMailExpress)(struct icq_link *link,unsigned char hour, + unsigned char minute, unsigned char day, unsigned char month, + unsigned short year, const char *nick, const char *email, + const char *msg); + void (*icq_RecvChatReq)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *descr, + unsigned long seq); + void (*icq_RecvFileReq)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *descr, + const char *filename, unsigned long filesize, unsigned long seq); + void (*icq_RecvAdded)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *nick, + const char *first, const char *last, const char *email); + void (*icq_RecvAuthReq)(struct icq_link *link, unsigned long uin, + unsigned char hour, unsigned char minute, unsigned char day, + unsigned char month, unsigned short year, const char *nick, + const char *first, const char *last, const char *email, + const char *reason); + void (*icq_UserFound)(struct icq_link *link, unsigned long uin, + const char *nick, const char *first, const char *last, + const char *email, char auth); + void (*icq_SearchDone)(struct icq_link *link); + void (*icq_UserOnline)(struct icq_link *link, unsigned long uin, + unsigned long status, unsigned long ip, unsigned short port, + unsigned long real_ip, unsigned char tcp_flag ); + void (*icq_UserOffline)(struct icq_link *link, unsigned long uin); + void (*icq_UserStatusUpdate)(struct icq_link *link, unsigned long uin, + unsigned long status); + void (*icq_InfoReply)(struct icq_link *link, unsigned long uin, + const char *nick, const char *first, const char *last, + const char *email, char auth); + void (*icq_ExtInfoReply)(struct icq_link *link, unsigned long uin, + const char *city, unsigned short country_code, char country_stat, + const char *state, unsigned short age, char gender, + const char *phone, const char *hp, const char *about); + void (*icq_WrongPassword)(struct icq_link *link); + void (*icq_InvalidUIN)(struct icq_link *link); + void (*icq_Log)(struct icq_link *link, time_t time, unsigned char level, + const char *str); + void (*icq_SrvAck)(struct icq_link *link, unsigned short seq); + void (*icq_RequestNotify)(struct icq_link *link, unsigned long id, int result, + unsigned int length, void *data); + void (*icq_NewUIN)(struct icq_link *link, unsigned long uin); + void (*icq_SetTimeout)(struct icq_link *link, long interval); + void (*icq_MetaUserFound)(struct icq_link *link, unsigned short seq2, + unsigned long uin, const char *nick, const char *first, + const char *last, const char *email, char auth); + void (*icq_MetaUserInfo)(struct icq_link *link, unsigned short seq2, + const char *nick, const char *first, const char *last, + const char *pri_eml, const char *sec_eml, const char *old_eml, + const char *city, const char *state, const char *phone, const char *fax, + const char *street, const char *cellular, unsigned long zip, + unsigned short country, unsigned char timezone, unsigned char auth, + unsigned char webaware, unsigned char hideip); + void (*icq_MetaUserWork)(struct icq_link *link, unsigned short seq2, + const char *wcity, const char *wstate, const char *wphone, + const char *wfax, const char *waddress, unsigned long wzip, + unsigned short wcountry, const char *company, const char *department, + const char *job, unsigned short occupation, const char *whomepage); + void (*icq_MetaUserMore)(struct icq_link *link, unsigned short seq2, + unsigned short age, unsigned char gender, const char *homepage, + unsigned char byear, unsigned char bmonth, unsigned char bday, + unsigned char lang1, unsigned char lang2, unsigned char lang3); + void (*icq_MetaUserAbout)(struct icq_link *link, unsigned short seq2, + const char *about); + void (*icq_MetaUserInterests)(struct icq_link *link, unsigned short seq2, + unsigned char num, unsigned short icat1, const char *int1, + unsigned short icat2, const char *int2, unsigned short icat3, + const char *int3, unsigned short icat4, const char *int4); + void (*icq_MetaUserAffiliations)(struct icq_link *link, unsigned short seq2, + unsigned char anum, unsigned short acat1, const char *aff1, + unsigned short acat2, const char *aff2, unsigned short acat3, + const char *aff3, unsigned short acat4, const char *aff4, + unsigned char bnum, unsigned short bcat1, const char *back1, + unsigned short bcat2, const char *back2, unsigned short bcat3, + const char *back3, unsigned short bcat4, const char *back4); + void (*icq_MetaUserHomePageCategory)(struct icq_link *link, + unsigned short seq2, unsigned char num, unsigned short hcat1, + const char *htext1); +} ICQLINK; + +extern int icq_Russian; +extern unsigned char icq_LogLevel; +extern icq_ArrayType icq_Countries[]; + +void icq_SetProxy(ICQLINK *link, const char *phost, unsigned short pport, + int pauth, const char *pname, const char *ppass); +void icq_UnsetProxy(ICQLINK *link); + +void icq_Init(ICQLINK *link, unsigned long uin, const char *password, + const char *nick); +void icq_Done(ICQLINK *link); +int icq_Connect(ICQLINK *link, const char *hostname, int port); +void icq_Disconnect(ICQLINK *link); +int icq_GetSok(ICQLINK *link); +int icq_GetProxySok(ICQLINK *link); +void icq_HandleServerResponse(ICQLINK *link); +void icq_HandleProxyResponse(ICQLINK *link); +void icq_HandleTimeout(ICQLINK *link); +void icq_Main(ICQLINK *link); +unsigned short icq_KeepAlive(ICQLINK *link); +void icq_Login(ICQLINK *link, unsigned long status); +void icq_Logout(ICQLINK *link); +void icq_SendContactList(ICQLINK *link); +void icq_SendVisibleList(ICQLINK *link); +void icq_SendNewUser(ICQLINK * link, unsigned long uin); +unsigned long icq_SendMessage(ICQLINK *link, unsigned long uin, + const char *text, unsigned char thruSrv); +unsigned long icq_SendURL(ICQLINK *link, unsigned long uin, const char *url, + const char *descr, unsigned char thruSrv); +void icq_ChangeStatus(ICQLINK *link, unsigned long status); +unsigned short icq_SendInfoReq(ICQLINK *link, unsigned long uin); +unsigned short icq_SendExtInfoReq(ICQLINK *link, unsigned long uin); +unsigned short icq_SendAuthMsg(ICQLINK *link, unsigned long uin); +void icq_SendSearchReq(ICQLINK *link, const char *email, const char *nick, + const char* first, const char* last); +void icq_SendSearchUINReq(ICQLINK *link, unsigned long uin); + +const char *icq_GetCountryName(unsigned short code); +const char *icq_GetMetaOccupationName(unsigned short code); +const char *icq_GetMetaBackgroundName(unsigned short code); +const char *icq_GetMetaAffiliationName(unsigned short code); +const char *icq_GetMetaLanguageName(unsigned short code); +void icq_RegNewUser(ICQLINK *link, const char *pass); +unsigned short icq_UpdateUserInfo(ICQLINK *link, const char *nick, + const char *first, const char *last, const char *email); +unsigned short icq_UpdateAuthInfo(ICQLINK *link, unsigned long auth); +unsigned short icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick, + const char *first, const char *last, const char *email, + const char *email2, const char *email3, const char *city, + const char *state, const char *phone, const char *fax, const char *street, + const char *cellular, unsigned long zip, unsigned short cnt_code, + unsigned char cnt_stat, unsigned char emailhide); +unsigned short icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age, + const char *homepage, unsigned char year, unsigned char month, + unsigned char day, unsigned char lang1, unsigned char lang2, + unsigned char lang3); +unsigned short icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about); +unsigned short icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth, + unsigned char webpresence, unsigned char pubip); +unsigned short icq_UpdateNewUserInfo(ICQLINK *link, const char *nick, + const char *first, const char *last, const char *email); +unsigned short icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin); + +void icq_FmtLog(ICQLINK *link, int level, const char *fmt, ...); + +void icq_ContactAdd(ICQLINK *link, unsigned long cuin); +void icq_ContactRemove(ICQLINK *link, unsigned long cuin); +void icq_ContactClear(ICQLINK *link ); +void icq_ContactSetVis(ICQLINK *link, unsigned long cuin, unsigned char vu); + +/*** TCP ***/ +void icq_TCPMain(ICQLINK *link); + +void icq_TCPProcessReceived(ICQLINK *link); + +unsigned long icq_TCPSendMessage(ICQLINK *link, unsigned long uin, + const char *message); +unsigned long icq_TCPSendURL(ICQLINK *link, unsigned long uin, + const char *message, const char *url); +unsigned long icq_SendChatRequest(ICQLINK *link, unsigned long uin, + const char *message); +void icq_AcceptChatRequest(ICQLINK *link, unsigned long uin, unsigned long seq); + +void icq_TCPSendChatData(ICQLINK *link, unsigned long uin, const char *data); +void icq_TCPSendChatData_n(ICQLINK *link, unsigned long uin, const char *data, int len); +void icq_TCPCloseChat(ICQLINK *link, unsigned long uin); + +void icq_CancelChatRequest(ICQLINK *link, unsigned long uin, + unsigned long sequence); +void icq_RefuseChatRequest(ICQLINK *link, unsigned long uin, + unsigned long sequence, const char *reason); + +/*** TCP ***/ + +/* file session statuses- request receiver */ +#define FILE_STATUS_LISTENING 1 +#define FILE_STATUS_CONNECTED 3 + +/* file session statuses- request sender */ +#define FILE_STATUS_CONNECTING 2 + +#define FILE_STATUS_INITIALIZED 4 +#define FILE_STATUS_NEXT_FILE 5 +#define FILE_STATUS_STOP_FILE 6 +#define FILE_STATUS_NEW_SPEED 7 + +/* once negotiation is complete, file session enters proper state */ +#define FILE_STATUS_READY 8 +#define FILE_STATUS_SENDING 8 +#define FILE_STATUS_RECEIVING 9 + +struct icq_TCPLink_s; + +typedef struct icq_FileSession_s { + + unsigned long id; + int status; + ICQLINK *icqlink; + struct icq_TCPLink_s *tcplink; + + int direction; + + unsigned long remote_uin; + char remote_handle[64]; + + char **files; + int total_files; + int current_file_num; + unsigned long total_bytes; + unsigned long total_transferred_bytes; + + char working_dir[512]; + char current_file[64]; + int current_fd; + unsigned long current_file_size; + unsigned long current_file_progress; + + int current_speed; + +} icq_FileSession; + +icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, unsigned long uin, + unsigned long sequence); +unsigned long icq_SendFileRequest(ICQLINK *link, unsigned long uin, + const char *message, char **files); +void icq_CancelFileRequest(ICQLINK *link, unsigned long uin, + unsigned long sequence); +void icq_RefuseFileRequest(ICQLINK *link, unsigned long uin, + unsigned long sequence, const char *reason); + +void icq_FileSessionSetSpeed(icq_FileSession *p, int speed); +void icq_FileSessionClose(icq_FileSession *p); +void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir); +void icq_FileSessionSetFiles(icq_FileSession *p, char **files); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _ICQ_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqbyteorder.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,50 @@ +/* + * $Id: icqbyteorder.c 1162 2000-11-28 02:22:42Z warmenhoven $ + * + * This header defines macros to handle ICQ protocol byte order conversion. + * + * Vadim Zaliva <lord@crocodile.org> + * http://www.crocodile.org/ + * + * Copyright (C) 1999 Vadim Zaliva + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * I am really trying to use builtin optimized byte swap routines. + * they are highly optimised on some platforms. + * But as last resort this simple code is used. + */ +#ifndef HAVE_BYTESWAP_H +# ifndef bswap_32 +unsigned long bswap_32(unsigned long v) +{ + unsigned char c,*x=(unsigned char *)&v; + c=x[0];x[0]=x[3];x[3]=c; + c=x[1];x[1]=x[2];x[2]=c; + return v; +} +# endif +# ifndef bswap_16 +unsigned short bswap_16(unsigned short v) +{ + unsigned char c,*x=(unsigned char *)&v; + c=x[0];x[0]=x[1];x[1]=c; + return v; +} +# endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqbyteorder.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,116 @@ +/* + * $Id: icqbyteorder.h 1162 2000-11-28 02:22:42Z warmenhoven $ + * + * This header defines macros to handle ICQ protocol byte order conversion. + * + * Vadim Zaliva <lord@crocodile.org> + * http://www.crocodile.org/ + * + * Copyright (C) 1999 Vadim Zaliva + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * From ICQ protocol description: + * "Integers consisting of more than one byte is stored + * with the least significant byte first, and the most significant byte last + * (as is usual on the PC/Intel architecture)". + * + * whereas the network byte order, as used on the + * Internet, is Most Significant Byte first. (aka. Big Endian) + */ + +#ifndef ICQ_BYTEORDER_H_FLAG +#define ICQ_BYTEORDER_H_FLAG + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* linux way */ +#ifdef HAVE_ENDIAN_H +# include <endian.h> +#endif +#ifdef HAVE_BYTESWAP_H +# include <byteswap.h> +#endif + +/* bsd way */ +#ifdef HAVE_MACHINE_ENDIAN_H +# include <machine/endian.h> +#endif + +/* + * Kind of portable way. this common header, at least I found it on BSD and Solaris. + * On Solaris this is only place where endiannes is defined. + */ +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include <arpa/nameser_compat.h> +#endif + +/* + * I am really trying to use builtin optimized byte swap routines. + * they are highly optimised on some platforms. + * But as last resort this simple code is used. + */ +#ifndef HAVE_BYTESWAP_H +# ifndef bswap_32 +extern unsigned long bswap_32(unsigned long v); +# endif +# ifndef bswap_16 +extern unsigned short bswap_16(unsigned short v); +# endif +#endif + +#ifdef BYTE_ORDER_LITTLE_ENDIAN +# define htoicql(x) (x) +# define icqtohl(x) (x) +# define htoicqs(x) (x) +# define icqtohs(x) (x) +#else + +#ifndef BYTE_ORDER +# error "Unknown byte order!" +#endif + +#if BYTE_ORDER == BIG_ENDIAN +/* host is different from ICQ byte order */ +# define htoicql(x) bswap_32(x) +# define icqtohl(x) bswap_32(x) +# define htoicqs(x) bswap_16(x) +# define icqtohs(x) bswap_16(x) +#else +# if BYTE_ORDER == LITTLE_ENDIAN +/* host byte order match ICQ byte order */ +# define htoicql(x) (x) +# define icqtohl(x) (x) +# define htoicqs(x) (x) +# define icqtohs(x) (x) +# else +# error "Unsupported byte order!" +# endif +#endif + +#endif + +/* ICQ byte order is always different from network byte order. */ +# define ntoicql(x) bswap_32(x) +# define icqtonl(x) bswap_32(x) +# define ntoicqs(x) bswap_16(x) +# define icqtons(x) bswap_16(x) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqlib.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,621 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: icqlib.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.44 2000/07/24 03:10:08 bills +added support for real nickname during TCP transactions like file and +chat, instead of using Bill all the time (hmm, where'd I get that from? :) + +Revision 1.43 2000/07/09 22:05:11 bills +removed unnecessary functions + +Revision 1.42 2000/07/09 18:28:07 denis +Initial memset() in icq_Init() replaced by callback's clearance. + +Revision 1.41 2000/06/15 01:50:39 bills +removed *Seq functions + +Revision 1.40 2000/05/10 19:06:59 denis +UDP outgoing packet queue was implemented. + +Revision 1.39 2000/05/03 18:12:36 denis +Unfinished UDP queue was commented out. + +Revision 1.38 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.37 2000/04/06 16:38:04 denis +icq_*Send*Seq() functions with specified sequence number were added. + +Revision 1.36 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.35 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.34 1999/12/27 16:06:32 bills +cleanups + +Revision 1.33 1999/10/03 21:35:55 tim +Fixed "url" and "descr" parameters order when sending a URL via TCP. + +Revision 1.32 1999/09/29 16:49:43 denis +Host/network/icq byteorder systemized. +icq_Init() cleaned up. + +Revision 1.31 1999/07/18 20:15:55 bills +changed to use new byte-order functions & contact list functions + +Revision 1.30 1999/07/16 12:27:06 denis +Other global variables moved to ICQLINK structure. +Initialization of random number generator added in icq_Init() +Cleaned up. + +Revision 1.29 1999/07/12 15:13:31 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.28 1999/07/03 02:26:02 bills +added new code to support thruSrv arg to SendMessage and SendURL + +Revision 1.27 1999/04/17 19:21:37 bills +modified Send* Functions to return DWORD instead of WORD + +Revision 1.26 1999/04/14 14:48:18 denis +Switched from icq_Log callback to icq_Fmt function. +Cleanups for "strict" compiling (-ansi -pedantic) + +Revision 1.25 1999/04/05 13:14:57 denis +Send messages and URLs to 'not in list' users fixed. + +Revision 1.24 1999/03/31 01:43:40 bills +added TCP support to SendURL + +Revision 1.23 1999/03/30 22:47:44 lord +list of countries now sorted. + +Revision 1.22 1999/03/28 03:18:22 bills +enable tcp messaging in icq_SendMessage, uncommented icq_OurPort and +icq_OurIp and fixed function names so icqlib compiles + +Revision 1.21 1999/03/25 22:16:43 bills +added #include "util.h" + +Revision 1.20 1999/03/24 11:37:36 denis +Underscored files with TCP stuff renamed. +TCP stuff cleaned up +Function names changed to corresponding names. +icqlib.c splitted to many small files by subject. +C++ comments changed to ANSI C comments. + +Revision 1.19 1999/03/22 20:51:28 bills +added code in icq_HandleUserOnline to set/clear new struct entries in +icq_ContactItem; added cleanup code in icq_HandleUserOffline for same + +Revision 1.18 1999/03/09 13:14:05 denis +Cyrillic recoding removed from URLs + +Revision 1.17 1999/03/05 13:57:54 denis +Some cosmetic changes... + +Revision 1.16 1998/12/08 16:00:59 denis +Cleaned up a little before releasing + +Revision 1.15 1998/11/25 19:18:16 denis +Added close icq_ProxySok in icq_Disconnect + +Revision 1.14 1998/11/25 09:48:49 denis +icq_GetProxySok and icq_HandleProxyResponse methods added +Connection terminated support added + +Revision 1.13 1998/11/19 12:22:48 denis +SOCKS support cleaned a little +icq_RecvUrl renamed to icq_RecvURL +icq_ProxyAuth added for Username/Password Authentication +URL/Description order inverted +icq_Quit splitted to icq_Logout and icq_Disconnect +icq_ProxyName and icq_ProxyPass range checking added + +Revision 1.12 1998/11/18 16:21:29 denis +Fixed SOCKS5 proxy support + + */ + +#include "icqlib.h" + +#include <stdlib.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include <time.h> + +#ifdef _WIN32 +#include <winsock.h> +#else +#include <netdb.h> +#include <sys/socket.h> +#endif + +#include <sys/stat.h> + +#ifndef _WIN32 +#include <sys/time.h> +#include <netinet/in.h> +#endif + +#include "util.h" +#include "icqtypes.h" +#include "icq.h" +#include "udp.h" +#include "tcp.h" +#include "queue.h" + +int icq_Russian = FALSE; +BYTE icq_LogLevel = 0; + +DWORD icq_SendMessage(ICQLINK *link, DWORD uin, const char *text, BYTE thruSrv) +{ + if(thruSrv==ICQ_SEND_THRUSERVER) + return icq_UDPSendMessage(link, uin, text); + else if(thruSrv==ICQ_SEND_DIRECT) + return icq_TCPSendMessage(link, uin, text); + else if(thruSrv==ICQ_SEND_BESTWAY) + { + icq_ContactItem *pcontact=icq_ContactFind(link, uin); + if(pcontact) + { + if(pcontact->tcp_flag == 0x04) + return icq_TCPSendMessage(link, uin, text); + else + return icq_UDPSendMessage(link, uin, text); + } + else + { + return icq_UDPSendMessage(link, uin, text); + } + } + return 0; +} + +DWORD icq_SendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr, BYTE thruSrv) +{ + if(thruSrv==ICQ_SEND_THRUSERVER) + return icq_UDPSendURL(link, uin, url, descr); + else if(thruSrv==ICQ_SEND_DIRECT) + return icq_TCPSendURL(link, uin, descr, url); + else if(thruSrv==ICQ_SEND_BESTWAY) + { + icq_ContactItem *pcontact=icq_ContactFind(link, uin); + if(pcontact) + { + if(pcontact->tcp_flag == 0x04) + return icq_TCPSendURL(link, uin, descr, url); + else + return icq_UDPSendURL(link, uin, url, descr); + } + else + { + return icq_UDPSendURL(link, uin, url, descr); + } + } + return 0; +} + +void icq_Init(ICQLINK *link, DWORD uin, const char *password, + const char *nick) +{ + srand(time(0L)); +/* memset(link, 0, sizeof(ICQLINK)); */ + + /* Initialize all callbacks */ + link->icq_Logged = 0L; + link->icq_Disconnected = 0L; + link->icq_RecvMessage = 0L; + link->icq_RecvURL = 0L; + link->icq_RecvWebPager = 0L; + link->icq_RecvMailExpress = 0L; + link->icq_RecvChatReq = 0L; + link->icq_RecvFileReq = 0L; + link->icq_RecvAdded = 0L; + link->icq_RecvAuthReq = 0L; + link->icq_UserFound = 0L; + link->icq_SearchDone = 0L; + link->icq_UserOnline = 0L; + link->icq_UserOffline = 0L; + link->icq_UserStatusUpdate = 0L; + link->icq_InfoReply = 0L; + link->icq_ExtInfoReply = 0L; + link->icq_WrongPassword = 0L; + link->icq_InvalidUIN = 0L; + link->icq_Log = 0L; + link->icq_SrvAck = 0L; + link->icq_RequestNotify = 0L; + link->icq_NewUIN = 0L; + link->icq_SetTimeout = 0L; + link->icq_MetaUserFound = 0L; + link->icq_MetaUserInfo = 0L; + link->icq_MetaUserWork = 0L; + link->icq_MetaUserMore = 0L; + link->icq_MetaUserAbout = 0L; + link->icq_MetaUserInterests = 0L; + link->icq_MetaUserAffiliations = 0L; + link->icq_MetaUserHomePageCategory = 0L; + + /* General stuff */ + link->icq_Uin = uin; + link->icq_Password = strdup(password); + link->icq_Nick = strdup(nick); + link->icq_OurIP = -1; + link->icq_OurPort = 0; + link->icq_ContactList = list_new(); + link->icq_Status = -1; + + /* UDP stuff */ + link->icq_UDPSok = -1; + memset(link->icq_UDPServMess, FALSE, sizeof(link->icq_UDPServMess)); + link->icq_UDPSeqNum1 = 0; + link->icq_UDPSeqNum2 = 0; + link->icq_UDPSession = 0; + icq_UDPQueueNew(link); + + icq_TCPInit(link); + + /* Proxy stuff */ + link->icq_UseProxy = 0; + link->icq_ProxyHost = 0L; + link->icq_ProxyIP = -1; + link->icq_ProxyPort = 0; + link->icq_ProxyAuth = 0; + link->icq_ProxyName = 0L; + link->icq_ProxyPass = 0L; + link->icq_ProxySok = -1; + link->icq_ProxyOurPort = 0; + link->icq_ProxyDestIP = -1; + link->icq_ProxyDestPort = 0; +} + +void icq_Done(ICQLINK *link) +{ + icq_TCPDone(link); + if(link->icq_Password) + free(link->icq_Password); + if(link->icq_Nick) + free(link->icq_Nick); + if(link->icq_ContactList) + list_delete(link->icq_ContactList, icq_ContactDelete); + icq_UDPQueueDelete(link); +} + +/****************************** +Main function connects gets icq_Uin +and icq_Password and logins in and sits +in a loop waiting for server responses. +*******************************/ +void icq_Main(ICQLINK *link) +{ + struct timeval tv; + fd_set readfds; + + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(link->icq_UDPSok, &readfds); + select(link->icq_UDPSok+1, &readfds, 0L, 0L, &tv); + if(FD_ISSET(link->icq_UDPSok, &readfds)) + icq_HandleServerResponse(link); + icq_TCPMain(link); +} + +/********************************** +Connects to hostname on port port +hostname can be DNS or nnn.nnn.nnn.nnn +write out messages to the FD aux +***********************************/ +int icq_Connect(ICQLINK *link, const char *hostname, int port) +{ + char buf[1024]; /*, un = 1;*/ +/* char tmpbuf[256], our_host[256]*/ + int conct, res; + unsigned int length; + struct sockaddr_in sin, prsin; /* used to store inet addr stuff */ + struct hostent *host_struct; /* used in DNS llokup */ + + link->icq_UDPSok = socket(AF_INET, SOCK_DGRAM, 0);/* create the unconnected socket*/ + if(link->icq_UDPSok == -1) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "Socket creation failed\n"); + return -1; + } + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Socket created attempting to connect\n"); + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_family = AF_INET; /* we're using the inet not appletalk*/ + sin.sin_port = 0; + if(bind(link->icq_UDPSok, (struct sockaddr*)&sin, sizeof(struct sockaddr))<0) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "Can't bind socket to free port\n"); + return -1; + } + length = sizeof(sin); + getsockname(link->icq_UDPSok, (struct sockaddr*)&sin, &length); + link->icq_ProxyOurPort = ntohs(sin.sin_port); + if(link->icq_UseProxy) + { + icq_FmtLog(link, ICQ_LOG_MESSAGE, "[SOCKS] Trying to use SOCKS5 proxy\n"); + prsin.sin_addr.s_addr = inet_addr(link->icq_ProxyHost); + if(prsin.sin_addr.s_addr == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */ + { + host_struct = gethostbyname(link->icq_ProxyHost); + if(host_struct == 0L) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Can't find hostname: %s\n", link->icq_ProxyHost); + return -1; + } + prsin.sin_addr = *((struct in_addr*)host_struct->h_addr); + } + link->icq_ProxyIP = ntohl(prsin.sin_addr.s_addr); + prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/ + prsin.sin_port = htons(link->icq_ProxyPort); /* port */ + link->icq_ProxySok = socket(AF_INET, SOCK_STREAM, 0);/* create the unconnected socket*/ + if(link->icq_ProxySok == -1) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Socket creation failed\n"); + return -1; + } + icq_FmtLog(link, ICQ_LOG_MESSAGE, "[SOCKS] Socket created attempting to connect\n"); + conct = connect(link->icq_ProxySok, (struct sockaddr *) &prsin, sizeof(prsin)); + if(conct == -1) /* did we connect ?*/ + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); + return -1; + } + buf[0] = 5; /* protocol version */ + buf[1] = 1; /* number of methods */ + if(!strlen(link->icq_ProxyName) || !strlen(link->icq_ProxyPass) || !link->icq_ProxyAuth) + buf[2] = 0; /* no authorization required */ + else + buf[2] = 2; /* method username/password */ +#ifdef _WIN32 + send(link->icq_ProxySok, buf, 3, 0); + res = recv(link->icq_ProxySok, buf, 2, 0); +#else + write(link->icq_ProxySok, buf, 3); + res = read(link->icq_ProxySok, buf, 2); +#endif + if(strlen(link->icq_ProxyName) && strlen(link->icq_ProxyPass) && link->icq_ProxyAuth) + { + if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/ + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + return -1; + } + buf[0] = 1; /* version of subnegotiation */ + buf[1] = strlen(link->icq_ProxyName); + memcpy(&buf[2], link->icq_ProxyName, buf[1]); + buf[2+buf[1]] = strlen(link->icq_ProxyPass); + memcpy(&buf[3+buf[1]], link->icq_ProxyPass, buf[2+buf[1]]); +#ifdef _WIN32 + send(link->icq_ProxySok, buf, buf[1]+buf[2+buf[1]]+3, 0); + res = recv(link->icq_ProxySok, buf, 2, 0); +#else + write(link->icq_ProxySok, buf, buf[1]+buf[2+buf[1]]+3); + res = read(link->icq_ProxySok, buf, 2); +#endif + if(res != 2 || buf[0] != 1 || buf[1] != 0) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n"); +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + return -1; + } + } + else + { + if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */ + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + return -1; + } + } + buf[0] = 5; /* protocol version */ + buf[1] = 3; /* command UDP associate */ + buf[2] = 0; /* reserved */ + buf[3] = 1; /* address type IP v4 */ + buf[4] = (char)0; + buf[5] = (char)0; + buf[6] = (char)0; + buf[7] = (char)0; + *(unsigned short*)&buf[8] = htons(link->icq_ProxyOurPort); +/* memcpy(&buf[8], &link->icq_ProxyOurPort, 2); */ +#ifdef _WIN32 + send(link->icq_ProxySok, buf, 10, 0); + res = recv(link->icq_ProxySok, buf, 10, 0); +#else + write(link->icq_ProxySok, buf, 10); + res = read(link->icq_ProxySok, buf, 10); +#endif + if(res != 10 || buf[0] != 5 || buf[1] != 0) + { + switch(buf[1]) + { + case 1: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] General SOCKS server failure\n"); + break; + case 2: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection not allowed by ruleset\n"); + break; + case 3: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Network unreachable\n"); + break; + case 4: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Host unreachable\n"); + break; + case 5: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); + break; + case 6: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] TTL expired\n"); + break; + case 7: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Command not supported\n"); + break; + case 8: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Address type not supported\n"); + break; + default: + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n"); + break; + } +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + return -1; + } + } + sin.sin_addr.s_addr = inet_addr(hostname); /* checks for n.n.n.n notation */ + if(sin.sin_addr.s_addr == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */ + { + host_struct = gethostbyname(hostname); + if(host_struct == 0L) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "Can't find hostname: %s\n", hostname); + if(link->icq_UseProxy) + { +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + } + return -1; + } + sin.sin_addr = *((struct in_addr *)host_struct->h_addr); + } + if(link->icq_UseProxy) + { + link->icq_ProxyDestIP = ntohl(sin.sin_addr.s_addr); + memcpy(&sin.sin_addr.s_addr, &buf[4], 4); + } + sin.sin_family = AF_INET; /* we're using the inet not appletalk*/ + sin.sin_port = htons(port); /* port */ + if(link->icq_UseProxy) + { + link->icq_ProxyDestPort = port; + memcpy(&sin.sin_port, &buf[8], 2); + } + conct = connect(link->icq_UDPSok, (struct sockaddr*)&sin, sizeof(sin)); + if(conct == -1) /* did we connect ?*/ + { + icq_FmtLog(link, ICQ_LOG_FATAL, "Connection refused\n"); + if(link->icq_UseProxy) + { +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + } + return -1; + } + length = sizeof(sin) ; + getsockname(link->icq_UDPSok, (struct sockaddr*)&sin, &length); + link->icq_OurIP = ntohl(sin.sin_addr.s_addr); + link->icq_OurPort = ntohs(sin.sin_port); + return link->icq_UDPSok; +} + +void icq_Disconnect(ICQLINK *link) +{ +#ifdef _WIN32 + closesocket(link->icq_UDPSok); +#else + close(link->icq_UDPSok); +#endif + if(link->icq_UseProxy) + { +#ifdef _WIN32 + closesocket(link->icq_ProxySok); +#else + close(link->icq_ProxySok); +#endif + } + icq_UDPQueueFree(link); +} + +/* +void icq_InitNewUser(const char *hostname, DWORD port) +{ + srv_net_icq_pak pak; + int s; + struct timeval tv; + fd_set readfds; + + icq_Connect(hostname, port); + if((icq_UDPSok == -1) || (icq_UDPSok == 0)) + { + printf("Couldn't establish connection\n"); + exit(1); + } + icq_RegNewUser(icq_Password); + for(;;) + { + tv.tv_sec = 2; + tv.tv_usec = 500000; + + FD_ZERO(&readfds); + FD_SET(icq_UDPSok, &readfds); + + select(icq_UDPSok+1, &readfds, 0L, 0L, &tv); + + if(FD_ISSET(icq_UDPSok, &readfds)) + { + s = icq_UDPSockRead(icq_UDPSok, &pak.head, sizeof(pak)); + if(icqtohs(pak.head.cmd) == SRV_NEW_UIN) + { + icq_Uin = icqtohl(&pak.data[2]); + return; + } + } + } +} +*/ + +/************************ +icq_UDPServMess functions +*************************/ +BOOL icq_GetServMess(ICQLINK *link, WORD num) +{ + return ((link->icq_UDPServMess[num/8] & (1 << (num%8))) >> (num%8)); +} + +void icq_SetServMess(ICQLINK *link, WORD num) +{ + link->icq_UDPServMess[num/8] |= (1 << (num%8)); +} + +int icq_GetSok(ICQLINK *link) +{ + return link->icq_UDPSok; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqlib.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _ICQLIB_H_ +#define _ICQLIB_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* for strdup(), bzero() and snprintf() declarations */ +#ifndef __USE_BSD +#define __USE_BSD 1 +#define __need_bsd_undef 1 +#endif +#include <string.h> +#include <stdio.h> +#ifdef __need_bsd_undef +#undef __USE_BSD +#endif + +#include <sys/types.h> + +#include "util.h" +#include "contacts.h" + +BOOL icq_GetServMess(ICQLINK *link, WORD num); +void icq_SetServMess(ICQLINK *link, WORD num); +void icq_RusConv(const char to[4], char *t_in); +void icq_RusConv_n(const char to[4], char *t_in, int len); + +#ifndef _WIN32 +#ifndef inet_addr +extern unsigned long inet_addr(const char *cp); +#endif /* inet_addr */ +#ifndef inet_aton +extern int inet_aton(const char *cp, struct in_addr *inp); +#endif /* inet_aton */ +#ifndef inet_ntoa +extern char *inet_ntoa(struct in_addr in); +#endif /* inet_ntoa */ +#ifndef strdup +extern char *strdup(const char *s); +#endif /* strdup */ +#endif /* _WIN32 */ + +#endif /* _ICQLIB_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqpacket.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,387 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: icqpacket.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.10 2000/07/07 15:26:35 denis +"icq_Packet data overflow" log message temporarily commented out. + +Revision 1.9 2000/06/25 16:26:36 denis +icq_PacketUDPDump() tweaked a little. + +Revision 1.8 2000/05/03 18:20:40 denis +icq_PacketReadUDPInUIN() was added. + +Revision 1.7 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.6 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.5 1999/09/29 19:58:20 bills +cleanup + +Revision 1.4 1999/09/29 16:56:10 denis +Cleanups. + +Revision 1.3 1999/07/18 20:18:43 bills +changed to use new byte-order functions + +Revision 1.2 1999/07/16 15:45:05 denis +Cleaned up. + +Revision 1.1 1999/07/16 12:11:36 denis +UDP packet support added. +tcp_packet* functions renamed to icq_Packet* + +Revision 1.8 1999/07/12 15:13:38 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.7 1999/07/03 06:33:52 lord +. byte order conversion macros added +. some compilation warnings removed + +Revision 1.6 1999/04/17 19:36:50 bills +added tcp_packet_node_delete function and changed structure to include +list_node for new list routines. + +Revision 1.5 1999/04/14 15:08:04 denis +Cleanups for "strict" compiling (-ansi -pedantic) + +*/ + +/* + * ICQ packet abstraction + */ + +#include <stdlib.h> +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock.h> +#else +#include <sys/socket.h> +#endif + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "icqpacket.h" +#include "tcp.h" +#include "util.h" +#include "icqbyteorder.h" +#include "list.h" + +icq_Packet *icq_PacketNew() +{ + icq_Packet *p=(icq_Packet*)malloc(sizeof(icq_Packet)); + + p->length=0; + p->cursor=0; + p->id=0; + + return p; +} + +void icq_PacketDelete(void *p) +{ + free(p); +} + +void icq_PacketAppend32(icq_Packet *p, DWORD i) +{ + DWORD val=i; + + *(unsigned long*)((p->data)+(p->cursor))=htoicql(val); + icq_PacketAdvance(p, sizeof(DWORD)); +} + +void icq_PacketAppend32n(icq_Packet *p, DWORD i) +{ + DWORD val=i; + + *(DWORD *)((p->data)+(p->cursor)) = val; + icq_PacketAdvance(p, sizeof(DWORD)); +} + +DWORD icq_PacketRead32(icq_Packet *p) +{ + DWORD val; + + val = icqtohl(*(DWORD *)((p->data)+(p->cursor))); + icq_PacketAdvance(p, sizeof(DWORD)); + + return val; +} + +DWORD icq_PacketRead32n(icq_Packet *p) +{ + DWORD val; + + val = *(DWORD*)((p->data)+(p->cursor)); + icq_PacketAdvance(p, sizeof(DWORD)); + + return val; +} + +void icq_PacketAppend16(icq_Packet *p, WORD i) +{ + WORD val=i; + + *(WORD *)((p->data)+(p->cursor)) = htoicqs(val); + icq_PacketAdvance(p, sizeof(WORD)); +} + +void icq_PacketAppend16n(icq_Packet *p, WORD i) +{ + WORD val=i; + + *(WORD *)((p->data)+(p->cursor)) = val; + icq_PacketAdvance(p, sizeof(WORD)); +} + +WORD icq_PacketRead16(icq_Packet *p) +{ + WORD val; + + val = icqtohs(*(WORD *)((p->data)+(p->cursor))); + icq_PacketAdvance(p, sizeof(WORD)); + + return val; +} + +WORD icq_PacketRead16n(icq_Packet *p) +{ + WORD val; + + val = *(WORD*)((p->data)+(p->cursor)); + icq_PacketAdvance(p, sizeof(WORD)); + + return val; +} + +void icq_PacketAppend8(icq_Packet *p, BYTE i) +{ + BYTE val=i; + + memcpy((p->data)+(p->cursor), &val, sizeof(BYTE)); + icq_PacketAdvance(p, sizeof(BYTE)); +} + +BYTE icq_PacketRead8(icq_Packet *p) +{ + BYTE val; + + memcpy(&val, (p->data)+(p->cursor), sizeof(BYTE)); + icq_PacketAdvance(p, sizeof(BYTE)); + + return val; +} + +void icq_PacketAppendString(icq_Packet *p, const char *s) +{ + if(s) + { + int length=strlen(s)+1; + + icq_PacketAppend16(p, length); + icq_PacketAppend(p, s, length); + } + else + { + icq_PacketAppend16(p, 1); + icq_PacketAppend8(p,0); + } +} + +const char *icq_PacketReadString(icq_Packet *p) +{ + int length=icq_PacketRead16(p); + + return (const char *)icq_PacketRead(p, length); +} + +char *icq_PacketReadStringNew(icq_Packet *p) +{ + char *ptr; + int length=icq_PacketRead16(p); + + ptr = (char*)malloc(length); + if(!ptr) + return 0L; + strncpy(ptr, icq_PacketRead(p, length), length); + return ptr; +} + +void icq_PacketAppendStringFE(icq_Packet *p, const char *s) +{ + if(s) + { + int length=strlen(s); + icq_PacketAppend(p, s, length); + } + icq_PacketAppend8(p, 0xFE); +} + +void icq_PacketAppendString0(icq_Packet *p, const char *s) +{ + if(s) + { + int length=strlen(s); + icq_PacketAppend(p, s, length); + } + icq_PacketAppend8(p, 0); +} + +WORD icq_PacketReadUDPOutVer(icq_Packet *p) +{ + icq_PacketGoto(p, 0); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPOutCmd(icq_Packet *p) +{ + icq_PacketGoto(p, 14 /*2*/); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPOutSeq1(icq_Packet *p) +{ + icq_PacketGoto(p, 16); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPOutSeq2(icq_Packet *p) +{ + icq_PacketGoto(p, 18 /*4*/); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPInVer(icq_Packet *p) +{ + icq_PacketGoto(p, 0); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPInCmd(icq_Packet *p) +{ + icq_PacketGoto(p, 7); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPInSeq1(icq_Packet *p) +{ + icq_PacketGoto(p, 9); + return icq_PacketRead16(p); +} + +WORD icq_PacketReadUDPInSeq2(icq_Packet *p) +{ + icq_PacketGoto(p, 11); + return icq_PacketRead16(p); +} + +DWORD icq_PacketReadUDPInUIN(icq_Packet *p) +{ + icq_PacketGoto(p, 13); + return icq_PacketRead32(p); +} + +void icq_PacketAppend(icq_Packet *p, const void *data, int length) +{ + memcpy((p->data)+(p->cursor), data, length); + icq_PacketAdvance(p, length); +} + +const void *icq_PacketRead(icq_Packet *p, int length) +{ + const void *data=(p->data)+(p->cursor); + + icq_PacketAdvance(p, length); + + return data; +} + +void icq_PacketShortDump(icq_Packet *p) +{ + printf("icq_Packet %x { id=%d, cursor=%x, length=%d }\n", + (int)p, (int)p->id, p->cursor, p->length); +} + +void icq_PacketDump(icq_Packet *p) +{ + icq_PacketShortDump(p); + hex_dump((char*)&(p->length), p->length+sizeof(WORD)); +} + +void icq_PacketUDPDump(icq_Packet *p) +{ + icq_PacketShortDump(p); + hex_dump((char*)&(p->data), p->length); +} + +void icq_PacketBegin(icq_Packet *p) +{ + p->cursor=0; +} + +void icq_PacketEnd(icq_Packet *p) +{ + p->cursor=p->length; +} + +void icq_PacketAdvance(icq_Packet *p, int i) +{ + p->cursor+=i; + + if(p->cursor > p->length) + p->length=p->cursor; + +/* Do nothing, because we don't have ICQLINK here */ +/* if(p->cursor > ICQ_PACKET_DATA_SIZE) */ +/* icq_FmtLog(0L, ICQ_LOG_WARNING, "icq_Packet data overflow\n"); */ +} + +void icq_PacketGoto(icq_Packet *p, int i) +{ + icq_PacketBegin(p); + icq_PacketAdvance(p, i); +} + +void icq_PacketGotoUDPOutData(icq_Packet *p, int i) +{ + /* Go to data in UDP _client_ packet. */ + icq_PacketGoto(p, 24+i); +} + +void icq_PacketGotoUDPInData(icq_Packet *p, int i) +{ + /* Go to data in UDP _server_ packet. */ + icq_PacketGoto(p, 21+i); +} + +WORD icq_PacketPos(icq_Packet *p) +{ + return p->cursor; +} + +int icq_PacketSend(icq_Packet *p, int socket) +{ + int result; + + result=send(socket, (const char*)&(p->length), p->length+sizeof(WORD), 0); + +#ifdef TCP_RAW_TRACE + printf("%d bytes sent on socket %d, result %d\n", + p->length+1, socket, result); + icq_PacketDump(p); +#endif /* TCP_RAW_TRACE */ + + return result; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqpacket.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _ICQ_PACKET_H_ +#define _ICQ_PACKET_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icqtypes.h" + +#define ICQ_PACKET_DATA_SIZE 4096 + +typedef struct icq_Packet_s +{ + DWORD id; + WORD cursor; + WORD length; + BYTE data[ICQ_PACKET_DATA_SIZE]; +} icq_Packet; + +icq_Packet *icq_PacketNew(); +void icq_PacketDelete(void *); + +void icq_PacketAppend(icq_Packet *, const void *, int); +void icq_PacketAppend32(icq_Packet *, DWORD); +void icq_PacketAppend32n(icq_Packet *, DWORD); +void icq_PacketAppend16(icq_Packet *, WORD); +void icq_PacketAppend16n(icq_Packet *, WORD); +void icq_PacketAppend8(icq_Packet *, BYTE); +void icq_PacketAppendString(icq_Packet *, const char *); +void icq_PacketAppendStringFE(icq_Packet *, const char *); +void icq_PacketAppendString0(icq_Packet *, const char *); + +const void *icq_PacketRead(icq_Packet*, int); +DWORD icq_PacketRead32(icq_Packet*); +DWORD icq_PacketRead32n(icq_Packet*); +WORD icq_PacketRead16(icq_Packet*); +WORD icq_PacketRead16n(icq_Packet*); +BYTE icq_PacketRead8(icq_Packet*); +const char *icq_PacketReadString(icq_Packet*); +char *icq_PacketReadStringNew(icq_Packet*); +WORD icq_PacketReadUDPOutVer(icq_Packet*); +WORD icq_PacketReadUDPOutCmd(icq_Packet*); +WORD icq_PacketReadUDPOutSeq1(icq_Packet*); +WORD icq_PacketReadUDPOutSeq2(icq_Packet*); +WORD icq_PacketReadUDPInVer(icq_Packet*); +WORD icq_PacketReadUDPInCmd(icq_Packet*); +WORD icq_PacketReadUDPInSeq1(icq_Packet*); +WORD icq_PacketReadUDPInSeq2(icq_Packet*); +DWORD icq_PacketReadUDPInUIN(icq_Packet*); + +void icq_PacketDump(icq_Packet*); +void icq_PacketUDPDump(icq_Packet*); +void icq_PacketBegin(icq_Packet*); +void icq_PacketEnd(icq_Packet*); +void icq_PacketAdvance(icq_Packet*, int); +void icq_PacketGoto(icq_Packet*, int); +void icq_PacketGotoUDPOutData(icq_Packet*, int); +void icq_PacketGotoUDPInData(icq_Packet*, int); +WORD icq_PacketPos(icq_Packet*); +int icq_PacketSend(icq_Packet*, int); + +#endif /* _ICQ_PACKET_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/icqtypes.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,20 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _ICQTYPES_H_ +#define _ICQTYPES_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifndef _WIN32 +typedef unsigned long DWORD; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned char BOOL; +#endif + +typedef signed long S_DWORD; +typedef signed short S_WORD; +typedef signed char S_BYTE; + +#endif /* _ICQTYPES_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/list.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,273 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: list.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.14 2000/07/10 01:44:20 bills +i really don't learn - removed LIST_TRACE define + +Revision 1.13 2000/07/10 01:43:48 bills +argh - last list buglet fixed, removed free(node) call from list_free + +Revision 1.12 2000/07/10 01:31:17 bills +oops - removed #define LIST_TRACE and #define QUEUE_DEBUG + +Revision 1.11 2000/07/10 01:26:30 bills +added more trace messages, added list_remove_node call in list_free... +fixes list corruption bug introduced during last commit + +Revision 1.10 2000/07/09 22:04:45 bills +recoded list_free function - this was working very incorrectly! it was +only freeing the first node of the list, and then ending. fixes a memory +leak. + +Revision 1.9 2000/05/10 18:48:56 denis +list_free() was added to free but do not dispose the list. +Memory leak with destroying the list was fixed. + +Revision 1.8 2000/05/03 18:19:15 denis +Bug with empty contact list was fixed. + +Revision 1.7 2000/01/16 21:26:54 bills +fixed serious bug in list_remove + +Revision 1.6 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.5 1999/09/29 19:59:30 bills +cleanups + +Revision 1.4 1999/07/16 11:59:46 denis +list_first(), list_last(), list_at() added. +Cleaned up. + +*/ +/* + * linked list functions + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "list.h" + +list *list_new() +{ + list *plist=(list *)malloc(sizeof(list)); + + plist->head=0; + plist->tail=0; + plist->count=0; + + return plist; +} + +/* Frees all list nodes and list itself */ +void list_delete(list *plist, void (*item_free_f)(void *)) +{ + list_free(plist, item_free_f); + free(plist); +} + +/* Only frees the list nodes */ +void list_free(list *plist, void (*item_free_f)(void *)) +{ + list_node *p=plist->head; + +#ifdef LIST_TRACE + printf("list_free(%p)\n", plist); + list_dump(plist); +#endif + + while(p) + { + list_node *ptemp=p; + + p=p->next; + (*item_free_f)((void *)ptemp->item); + list_remove_node(plist, ptemp); + } +} + +void list_insert(list *plist, list_node *pnode, void *pitem) +{ + list_node *pnew=(list_node *)malloc(sizeof(list_node)); + pnew->item=pitem; + +#ifdef LIST_TRACE + printf("inserting %x (node=%x) into list %x\n", pitem, pnew, plist); +#endif + + plist->count++; + + /* null source node signifies insert at end of list */ + if(!pnode) + { + pnew->previous=plist->tail; + pnew->next=0; + if(plist->tail) + plist->tail->next=pnew; + plist->tail=pnew; + + if(!plist->head) + plist->head=pnew; + } + else + { + pnew->previous=pnode->previous; + pnew->next=pnode; + + if(pnew->previous) + pnew->previous->next=pnew; + + if(pnew->next) + pnode->previous=pnew; + + if(plist->head==pnode) + plist->head=pnew; + } + +#ifdef LIST_TRACE + list_dump(plist); +#endif +} + +void *list_remove_node(list *plist, list_node *p) +{ + void *pitem; + + if(!p) + return 0; + +#ifdef LIST_TRACE + printf("removing %x (node=%x) from list %x\n", p->item, p, plist); +#endif + + plist->count--; + + if(p->next) + p->next->previous=p->previous; + + if(p->previous) + p->previous->next=p->next; + + if(plist->head==p) + plist->head=p->next; + + if(plist->tail==p) + plist->tail=p->previous; + + p->next=0; + p->previous=0; + +#ifdef LIST_TRACE + list_dump(plist); +#endif + + pitem=p->item; + + free(p); + + return pitem; +} + +void *list_traverse(list *plist, int (*item_f)(void *, va_list), ...) +{ + list_node *i=plist->head; + int f=0; + va_list ap; + +#ifdef LIST_TRACE + printf("list_traverse(%p)\n", plist); + list_dump(plist); +#endif + va_start(ap, item_f); + + /* call item_f for each item in list until end of list or item + * function returns 0 */ + while(i && !f) + { + list_node *pnext=i->next; + + if(!(f=(*item_f)(i->item, ap))) + i=pnext; + } + va_end(ap); + if (i) + return i->item; + else + return 0; +} + +int list_dump(list *plist) +{ + list_node *p=plist->head; + + printf("list %x { head=%x, tail=%x, count=%d }\ncontents: ", + (int)plist, (int)plist->head, (int)plist->tail, plist->count); + + while(p) + { + printf("%x, ", (int)p->item); + p=p->next; + } + printf("end\n"); + + return 0; +} + +void *list_first(list *plist) +{ + if(plist->head) + return plist->head->item; + else + return 0; +} + +void *list_last(list *plist) +{ + if(plist->tail) + return plist->tail->item; + else + return 0; +} + +void *list_at(list *plist, int num) +{ + list_node *ptr = plist->head; + while(ptr && num) + { + num--; + ptr = ptr->next; + } + if(!num) + return ptr->item; + else + return 0L; +} + +list_node *list_find(list *plist, void *pitem) +{ + list_node *p=plist->head; + + while(p) + { + if(p->item==pitem) + return p; + p=p->next; + } + return 0; +} + +void *list_remove(list *plist, void *pitem) +{ + list_node *p=list_find(plist, pitem); + + if(p) + return list_remove_node(plist, p); + else + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/list.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _LIST_H +#define _LIST_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdarg.h> + +#define list_enqueue(plist, p) \ + list_insert(plist, 0, p) + +#define list_dequeue(plist) \ + list_remove_node(plist, plist->head) + +typedef struct list_node_s +{ + struct list_node_s *next; + struct list_node_s *previous; + void *item; +} list_node; + +typedef struct list_s +{ + list_node *head; + list_node *tail; + int count; +} list; + +list *list_new(void); +void list_delete(list *plist, void (*item_free_f)(void *)); +void list_free(list *plist, void (*item_free_f)(void *)); +void list_insert(list *plist, list_node *pnode, void *pitem); +void *list_remove(list *plist, void *pitem); +void *list_traverse(list *plist, int (*item_f)(void *, va_list), ...); +int list_dump(list *plist); +void *list_first(list *plist); +void *list_last(list *plist); +void *list_at(list *plist, int num); +list_node *list_find(list *plist, void *pitem); +void *list_remove_node(list *plist, list_node *p); + +#endif /* _LIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/proxy.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,115 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: proxy.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.8 2000/05/10 18:51:23 denis +icq_Disconnect() now called before icq_Disconnected callback to +prevent high CPU usage in kicq's "reconnect on disconnect" code. + +Revision 1.7 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.6 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.5 1999/10/07 18:00:59 denis +proxy.h file removed. + +Revision 1.4 1999/07/16 12:01:06 denis +ICQLINK support added. + +Revision 1.3 1999/07/12 15:13:33 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.2 1999/04/14 14:51:42 denis +Switched from icq_Log callback to icq_Fmt function. +Cleanups for "strict" compiling (-ansi -pedantic) + +Revision 1.1 1999/03/24 11:37:38 denis +Underscored files with TCP stuff renamed. +TCP stuff cleaned up +Function names changed to corresponding names. +icqlib.c splitted to many small files by subject. +C++ comments changed to ANSI C comments. + +*/ + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#ifdef _WIN32 +#include <winsock.h> +#endif + +#include <stdlib.h> + +#include "util.h" +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" + +void icq_HandleProxyResponse(ICQLINK *link) +{ + int s; + char buf[256]; +#ifdef _WIN32 + s = recv(link->icq_ProxySok, buf, sizeof(buf), 0); +#else + s = read(link->icq_ProxySok, &buf, sizeof(buf)); +#endif + if(s<=0) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection terminated\n"); + icq_Disconnect(link); + if(link->icq_Disconnected) + (*link->icq_Disconnected)(link); + } +} + +/******************* +SOCKS5 Proxy support +********************/ +void icq_SetProxy(ICQLINK *link, const char *phost, unsigned short pport, int pauth, const char *pname, const char *ppass) +{ + if(link->icq_ProxyHost) + free(link->icq_ProxyHost); + if(link->icq_ProxyName) + free(link->icq_ProxyName); + if(link->icq_ProxyPass) + free(link->icq_ProxyPass); + if(strlen(pname)>255) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "[SOCKS] User name greater than 255 chars\n"); + link->icq_UseProxy = 0; + return; + } + if(strlen(ppass)>255) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "[SOCKS] User password greater than 255 chars\n"); + link->icq_UseProxy = 0; + return; + } + link->icq_UseProxy = 1; + link->icq_ProxyHost = strdup(phost); + link->icq_ProxyPort = pport; + link->icq_ProxyAuth = pauth; + link->icq_ProxyName = strdup(pname); + link->icq_ProxyPass = strdup(ppass); +} + +void icq_UnsetProxy(ICQLINK *link) +{ + link->icq_UseProxy = 0; +} + +int icq_GetProxySok(ICQLINK *link) +{ + return link->icq_ProxySok; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/queue.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,167 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: queue.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.9 2000/07/10 01:31:17 bills +oops - removed #define LIST_TRACE and #define QUEUE_DEBUG + +Revision 1.8 2000/07/10 01:26:56 bills +added more trace messages, reworked packet delete handling: now happens +during _icq_UDEQueueItemFree rather than during icq_UDPQueueDelSeq - fixes +memory leak + +Revision 1.7 2000/07/09 22:07:37 bills +use new list_free + +Revision 1.6 2000/06/25 16:30:05 denis +Some sanity checks were added to icq_UDPQueueDelete() and +icq_UDPQueueFree() + +Revision 1.5 2000/05/10 19:06:59 denis +UDP outgoing packet queue was implemented. + +Revision 1.4 2000/03/30 14:15:28 denis +Fixed FreeBSD warning about obsolete malloc.h header. + +Revision 1.3 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.2 1999/09/29 17:06:47 denis +ICQLINK compatibility added. + +Revision 1.1 1999/07/16 12:12:13 denis +Initial support for outgoing packet queue added. + +*/ + +#include <stdlib.h> +#include <time.h> + +#include "queue.h" +#include "list.h" + +void icq_UDPQueueNew(ICQLINK *link) +{ + link->icq_UDPQueue = list_new(); + link->icq_UDPExpireInterval = 15; /* expire interval = 15 sec */ +} + +void icq_UDPQueuePut(ICQLINK *link, icq_Packet *p, int attempt) +{ + icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)malloc(sizeof(icq_UDPQueueItem)); +#ifdef QUEUE_DEBUG + printf("icq_UDPQueuePut(seq=0x%04X, cmd=0x%04X)\n", icq_PacketReadUDPOutSeq1(p), + icq_PacketReadUDPOutCmd(p)); +#endif + ptr->attempts = attempt; + ptr->expire = time(0L)+link->icq_UDPExpireInterval; + ptr->pack = p; +#ifdef QUEUE_DEBUG + printf("enqueuing queueitem %p\n", ptr); +#endif + list_enqueue(link->icq_UDPQueue, ptr); +} + +icq_Packet *icq_UDPQueueGet(ICQLINK *link) +{ + icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue); + icq_Packet *pack = 0L; + if(ptr) + { + pack = ptr->pack; + list_remove(link->icq_UDPQueue, (list_node*)ptr); + } +#ifdef QUEUE_DEBUG + if(pack) + printf("icq_UDPQueueGet(cmd=0x%04X)\n", icq_PacketReadUDPOutCmd(pack)); +#endif + return pack; +} + +icq_Packet *icq_UDPQueuePeek(ICQLINK *link) +{ + icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue); + if(ptr) + return ptr->pack; + else + return 0L; +} + +void _icq_UDPQueueItemFree(void *p) +{ + icq_UDPQueueItem *pitem=(icq_UDPQueueItem *)p; + +#ifdef QUEUE_DEBUG + printf("_icq_UDPQueueItemFree(%p)\n", p); +#endif + + if (pitem->pack) + icq_PacketDelete(pitem->pack); + + free(p); +} + +/* Frees the queue and dispose it */ +void icq_UDPQueueDelete(ICQLINK *link) +{ +#ifdef QUEUE_DEBUG + printf("icq_UDPQueueDelete\n"); +#endif + if(link->icq_UDPQueue) + { + list_delete(link->icq_UDPQueue, _icq_UDPQueueItemFree); + link->icq_UDPQueue = 0; + } +} + +/* Only frees the queue */ +void icq_UDPQueueFree(ICQLINK *link) +{ +#ifdef QUEUE_DEBUG + printf("icq_UDPQueueFree\n"); +#endif + if(link->icq_UDPQueue) + list_free(link->icq_UDPQueue, _icq_UDPQueueItemFree); +} + +int icq_UDPQueueFindSeq(void *p, va_list data) +{ + WORD seq=va_arg(data, WORD); + return icq_PacketReadUDPOutSeq1(((icq_UDPQueueItem *)p)->pack) == seq; +} + +void icq_UDPQueueDelSeq(ICQLINK *link, WORD seq) +{ + icq_UDPQueueItem *ptr; +#ifdef QUEUE_DEBUG + printf("icq_UDPQueueDelSeq(seq=0x%04X", seq); +#endif + ptr = list_traverse(link->icq_UDPQueue, icq_UDPQueueFindSeq, seq); + if(ptr) + { +#ifdef QUEUE_DEBUG + printf(", cmd=0x%04X",icq_PacketReadUDPOutCmd(ptr->pack)); +#endif + list_remove(link->icq_UDPQueue, ptr); + _icq_UDPQueueItemFree(ptr); + } +#ifdef QUEUE_DEBUG + printf(")\n"); +#endif +} + +long icq_UDPQueueInterval(ICQLINK *link) +{ + long interval; + icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue); + if(ptr) + { + interval = ptr->expire - time(0L); + return interval>=0?interval:0; + } + return -1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/queue.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,29 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icq.h" +#include "icqpacket.h" + +typedef struct udp_item +{ + unsigned char attempts; + unsigned long expire; + icq_Packet *pack; +} icq_UDPQueueItem; + +void icq_UDPQueueNew(ICQLINK*); +void icq_UDPQueueFree(ICQLINK*); +void icq_UDPQueuePut(ICQLINK*, icq_Packet*, int); +icq_Packet *icq_UDPQueueGet(ICQLINK*); +icq_Packet *icq_UDPQueuePeek(ICQLINK*); +void icq_UDPQueueDelete(ICQLINK*); +void icq_UDPQueueFree(ICQLINK*); +void icq_UDPQueueDelSeq(ICQLINK*, WORD); +long icq_UDPQueueInterval(ICQLINK *); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/stdpackets.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,563 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: stdpackets.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.10 2000/06/15 01:51:23 bills +added creation functions for cancel and refuse operations + +Revision 1.9 2000/05/04 15:50:38 bills +warning cleanups + +Revision 1.8 2000/04/10 18:11:45 denis +ANSI cleanups. + +Revision 1.7 2000/04/06 16:38:04 denis +icq_*Send*Seq() functions with specified sequence number were added. + +Revision 1.6 2000/02/07 02:35:13 bills +slightly modified chat packets + +Revision 1.5 2000/01/20 19:59:15 bills +first implementation of sending file requests + +Revision 1.4 1999/09/29 20:12:32 bills +tcp_link*->icq_TCPLink* + +Revision 1.3 1999/09/29 17:07:48 denis +Host/network byteorder cleanups. + +Revision 1.2 1999/07/16 15:45:20 denis +Cleaned up. + +Revision 1.1 1999/07/16 12:13:11 denis +UDP packets support added. +tcppackets.[ch] files renamed to stdpackets.[ch] + +Revision 1.9 1999/07/12 15:13:39 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.8 1999/05/03 21:41:28 bills +initial file xfer support added- untested + +Revision 1.7 1999/04/17 19:39:09 bills +added new functions to create chat packets. removed unnecessary code. +added new function to create URL ack packet. + +Revision 1.6 1999/04/14 15:08:39 denis +Cleanups for "strict" compiling (-ansi -pedantic) + +*/ + +#include <stdlib.h> + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "tcp.h" +#include "stdpackets.h" + +icq_Packet *icq_TCPCreateInitPacket(icq_TCPLink *plink) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + int type=plink->type; + + icq_PacketAppend8(p, 0xFF); + icq_PacketAppend32(p, ICQ_TCP_VER); + if(type==TCP_LINK_MESSAGE) + icq_PacketAppend32n(p, htons(plink->icqlink->icq_TCPSrvPort)); + else + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, plink->icqlink->icq_Uin); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend8(p, 0x04); + if(type==TCP_LINK_FILE || type==TCP_LINK_CHAT) + icq_PacketAppend32(p, ntohs(plink->socket_address.sin_port)); + else + icq_PacketAppend32(p, 0x00000000); + + } + + return p; +} + +icq_Packet *icq_TCPCreateStdPacket(icq_TCPLink *plink, WORD icq_TCPCommand, + WORD type, const unsigned char *msg, WORD status, + WORD msg_command) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend32(p, plink->icqlink->icq_Uin); + icq_PacketAppend16(p, ICQ_TCP_VER); + icq_PacketAppend16(p, icq_TCPCommand); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, plink->icqlink->icq_Uin); + + icq_PacketAppend16(p, type); + icq_PacketAppendString(p, (char*)msg); + + /* FIXME: this should be the address the server returns to us, + * link->icq_OurIp */ + icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); + icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); + icq_PacketAppend32(p, ntohs(plink->socket_address.sin_port)); + icq_PacketAppend8(p, 0x04); + icq_PacketAppend16(p, status); + icq_PacketAppend16(p, msg_command); + } + + return p; +} + +icq_Packet *icq_TCPCreateMessagePacket(icq_TCPLink *plink, const unsigned char *message) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_MESSAGE, + ICQ_TCP_MSG_MSG, + message, + 0, /* status */ + ICQ_TCP_MSG_REAL); + + return p; +} + +icq_Packet *icq_TCPCreateURLPacket(icq_TCPLink *plink, const char *message, + const char *url) +{ + icq_Packet *p; + unsigned char *str=(unsigned char*)malloc(strlen(message)+strlen(url)+2); + + strcpy((char*)str, message); + *(str+strlen(message))=0xFE; + strcpy((char*)(str+strlen(message)+1), url); + + p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_MESSAGE, + ICQ_TCP_MSG_URL, + str, + 0, /* status */ + ICQ_TCP_MSG_REAL); + + free(str); + + return p; +} + +icq_Packet *icq_TCPCreateChatReqPacket(icq_TCPLink *plink, const unsigned char *message) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_MESSAGE, + ICQ_TCP_MSG_CHAT, + message, + 0, /* status */ + ICQ_TCP_MSG_REAL); + + icq_PacketAppendString(p, 0); + + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, 0x00000000); + + return p; +} + +icq_Packet *icq_TCPCreateChatReqAck(icq_TCPLink *plink, WORD port) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_CHAT, + 0, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + icq_PacketAppendString(p, 0); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateChatReqRefuse(icq_TCPLink *plink, WORD port, + const char *reason) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_CHAT, + reason, + ICQ_TCP_STATUS_REFUSE, + ICQ_TCP_MSG_ACK); + + icq_PacketAppendString(p, 0); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateChatReqCancel(icq_TCPLink *plink, WORD port) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_CANCEL, + ICQ_TCP_MSG_CHAT, + 0, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + icq_PacketAppendString(p, 0); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateFileReqAck(icq_TCPLink *plink, WORD port) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_FILE, + 0, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppendString(p, 0); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateFileReqRefuse(icq_TCPLink *plink, WORD port, + const char *reason) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_FILE, + reason, + ICQ_TCP_STATUS_REFUSE, + ICQ_TCP_MSG_ACK); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppendString(p, 0); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateFileReqCancel(icq_TCPLink *plink, WORD port) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_CANCEL, + ICQ_TCP_MSG_FILE, + 0, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + icq_PacketAppend16(p, htons(port)); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppendString(p, 0); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, port); + + return p; +} + +icq_Packet *icq_TCPCreateChatInfoPacket(icq_TCPLink *plink, const char *name, + DWORD foreground, DWORD background) +{ + icq_Packet *p=icq_PacketNew(); + + icq_PacketAppend32(p, 0x00000065); + icq_PacketAppend32(p, 0xfffffffa); + icq_PacketAppend32(p, plink->icqlink->icq_Uin); + icq_PacketAppendString(p, name); + icq_PacketAppend16(p, plink->socket_address.sin_port); + icq_PacketAppend32(p, foreground); + icq_PacketAppend32(p, background); + icq_PacketAppend8(p, 0x00); + + return p; + +} + +icq_Packet *icq_TCPCreateChatInfo2Packet(icq_TCPLink *plink, const char *name, + DWORD foreground, DWORD background) +{ + icq_Packet *p=icq_PacketNew(); + + icq_PacketAppend32(p, 0x00000064); + icq_PacketAppend32(p, plink->icqlink->icq_Uin); + icq_PacketAppendString(p, name); + icq_PacketAppend32(p, foreground); + icq_PacketAppend32(p, background); + + icq_PacketAppend32(p, 0x00070004); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend8(p, 0x04); + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend32(p, 0x000a); + icq_PacketAppend32(p, 0x0000); + icq_PacketAppendString(p, "Courier New"); + icq_PacketAppend8(p, 204); + icq_PacketAppend8(p, 49); + icq_PacketAppend8(p, 0x00); + + return p; +} + +icq_Packet *icq_TCPCreateChatFontInfoPacket(icq_TCPLink *plink) +{ + icq_Packet *p=icq_PacketNew(); + + icq_PacketAppend32(p, 0x00070004); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP)); + icq_PacketAppend8(p, 0x04); + icq_PacketAppend16(p, ntohs(plink->socket_address.sin_port)); /* Zero ? */ + icq_PacketAppend32(p, 0x000a); + icq_PacketAppend32(p, 0x0000); + icq_PacketAppendString(p, "Courier New"); + icq_PacketAppend8(p, 204); + icq_PacketAppend8(p, 49); + icq_PacketAppend8(p, 0x00); + + return p; +} + + +icq_Packet *icq_TCPCreateFileReqPacket(icq_TCPLink *plink, + const char *message, const char *filename, unsigned long size) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_MESSAGE, + ICQ_TCP_MSG_FILE, + (const unsigned char*)message, + 0, /* status */ + ICQ_TCP_MSG_REAL); + + icq_PacketAppend16(p, 0x0000); + icq_PacketAppend16(p, 0x0000); + + icq_PacketAppendString(p, filename); + + icq_PacketAppend32(p, size); + icq_PacketAppend32(p, 0x00000000); + + return p; +} + +void icq_TCPAppendSequence(ICQLINK *link, icq_Packet *p) +{ + p->id=link->icq_TCPSequence--; + icq_PacketEnd(p); + icq_PacketAppend32(p, p->id); +} + +void icq_TCPAppendSequenceN(ICQLINK *link, icq_Packet *p, DWORD seq) +{ + (void)link; + p->id=seq; + icq_PacketEnd(p); + icq_PacketAppend32(p, p->id); +} + +icq_Packet *icq_TCPCreateMessageAck(icq_TCPLink *plink, const unsigned char *message) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_MSG, + message, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + return p; +} + +icq_Packet *icq_TCPCreateURLAck(icq_TCPLink *plink, const unsigned char *message) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_URL, + message, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + return p; +} + + +icq_Packet *icq_TCPCreateFile00Packet(DWORD num_files, DWORD total_bytes, + DWORD speed, const char *name) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x00); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, num_files); + icq_PacketAppend32(p, total_bytes); + icq_PacketAppend32(p, speed); + icq_PacketAppendString(p, name); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile01Packet(DWORD speed, const char *name) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x01); + icq_PacketAppend32(p, speed); + icq_PacketAppendString(p, name); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile02Packet(const char *filename, DWORD filesize, + DWORD speed) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x02); + icq_PacketAppend8(p, 0x00); + icq_PacketAppendString(p, filename); + icq_PacketAppendString(p, 0); + icq_PacketAppend32(p, filesize); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, speed); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile03Packet(DWORD filesize, DWORD speed) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x03); + icq_PacketAppend32(p, filesize); + icq_PacketAppend32(p, 0x00000000); + icq_PacketAppend32(p, speed); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile04Packet(DWORD filenum) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x04); + icq_PacketAppend32(p, filenum); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile05Packet(DWORD speed) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x05); + icq_PacketAppend32(p, speed); + } + + return p; +} + +icq_Packet *icq_TCPCreateFile06Packet(int length, void *data) +{ + icq_Packet *p=icq_PacketNew(); + + if(p) + { + icq_PacketAppend8(p, 0x06); + icq_PacketAppend(p, data, length); + } + + return p; +} + +icq_Packet *icq_UDPCreateStdPacket(ICQLINK *link, WORD cmd) +{ + icq_Packet *p = icq_PacketNew(); + +/* if(!link->icq_UDPSession) + link->icq_UDPSession = rand() & 0x3FFFFFFF; + if(!link->icq_UDPSeqNum2) + link->icq_UDPSeqNum2 = rand() & 0x7FFF;*/ + + icq_PacketAppend16(p, ICQ_UDP_VER); /* ver */ + icq_PacketAppend32(p, 0); /* zero */ + icq_PacketAppend32(p, link->icq_Uin); /* uin */ + icq_PacketAppend32(p, link->icq_UDPSession); /* session */ + icq_PacketAppend16(p, cmd); /* cmd */ + icq_PacketAppend16(p, link->icq_UDPSeqNum1++); /* seq1 */ + icq_PacketAppend16(p, link->icq_UDPSeqNum2++); /* seq2 */ + icq_PacketAppend32(p, 0); /* checkcode */ + + return p; +} + +icq_Packet *icq_UDPCreateStdSeqPacket(ICQLINK *link, WORD cmd, WORD seq) +{ + icq_Packet *p = icq_PacketNew(); + + icq_PacketAppend16(p, ICQ_UDP_VER); /* ver */ + icq_PacketAppend32(p, 0); /* zero */ + icq_PacketAppend32(p, link->icq_Uin); /* uin */ + icq_PacketAppend32(p, link->icq_UDPSession); /* session */ + icq_PacketAppend16(p, cmd); /* cmd */ + icq_PacketAppend16(p, seq); /* seq1 */ + icq_PacketAppend16(p, 0); /* seq2 */ + icq_PacketAppend32(p, 0); /* checkcode */ + + return p; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/stdpackets.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _ICQTCPPACKETS_H +#define _ICQTCPPACKETS_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define ICQ_UDP_VER 0x0005 +#define ICQ_TCP_VER 0x0003 + +/* TCP Packet Commands */ +#define ICQ_TCP_HELLO 0xFF +#define ICQ_TCP_CANCEL 0x07D0 +#define ICQ_TCP_ACK 0x07DA +#define ICQ_TCP_MESSAGE 0x07EE + +/* TCP Message Types */ +#define ICQ_TCP_MSG_MSG 0x0001 +#define ICQ_TCP_MSG_CHAT 0x0002 +#define ICQ_TCP_MSG_FILE 0x0003 +#define ICQ_TCP_MSG_URL 0x0004 +#define ICQ_TCP_MSG_READAWAY 0x03E8 +#define ICQ_TCP_MSG_READOCCUPIED 0x03E9 +#define ICQ_TCP_MSG_READNA 0x03EA +#define ICQ_TCP_MSG_READDND 0x03EB +#define ICQ_TCP_MSG_READFFC 0x03EC + +/* TCP Message Command Types */ +#define ICQ_TCP_MSG_ACK 0x0000 +#define ICQ_TCP_MSG_AUTO 0x0000 +#define ICQ_TCP_MSG_REAL 0x0010 +#define ICQ_TCP_MSG_LIST 0x0020 +#define ICQ_TCP_MSG_URGENT 0x0040 +#define ICQ_TCP_MSG_INVISIBLE 0x0090 +#define ICQ_TCP_MSG_UNK_1 0x00A0 +#define ICQ_TCP_MSG_AWAY 0x0110 +#define ICQ_TCP_MSG_OCCUPIED 0x0210 +#define ICQ_TCP_MSG_UNK_2 0x0802 +#define ICQ_TCP_MSG_NA 0x0810 +#define ICQ_TCP_MSG_NA_2 0x0820 +#define ICQ_TCP_MSG_DND 0x1010 + +/* TCP Message Statuses */ +#define ICQ_TCP_STATUS_ONLINE 0x0000 +#define ICQ_TCP_STATUS_REFUSE 0x0001 +#define ICQ_TCP_STATUS_AWAY 0x0004 +#define ICQ_TCP_STATUS_OCCUPIED 0x0009 +#define ICQ_TCP_STATUS_DND 0x000A +#define ICQ_TCP_STATUS_NA 0x000E +#define ICQ_TCP_STATUS_FREE_CHAT ICQ_TCP_STATUS_ONLINE +#define ICQ_TCP_STATUS_INVISIBLE ICQ_TCP_STATUS_ONLINE + +#include "icqpacket.h" +#include "tcplink.h" + +icq_Packet *icq_TCPCreateInitPacket(icq_TCPLink *plink); +icq_Packet *icq_TCPCreateStdPacket(icq_TCPLink *plink, WORD icq_TCPCommand, + WORD type, const unsigned char *msg, WORD status, + WORD msg_command); +icq_Packet *icq_TCPCreateMessagePacket(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateURLPacket(icq_TCPLink *plink, const char *message, + const char *url); +icq_Packet *icq_TCPCreateChatReqPacket(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateFileReqPacket(icq_TCPLink *plink, + const char *message, const char *filename, DWORD size); +void icq_TCPAppendSequence(ICQLINK *link, icq_Packet *p); +void icq_TCPAppendSequenceN(ICQLINK *link, icq_Packet *p, DWORD seq); + +icq_Packet *icq_TCPCreateMessageAck(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateURLAck(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateWebPagerAck(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateChatReqAck(icq_TCPLink *plink, WORD port); +icq_Packet *icq_TCPCreateChatReqCancel(icq_TCPLink *plink, WORD port); +icq_Packet *icq_TCPCreateChatReqRefuse(icq_TCPLink *plink, WORD port, + const char *reason); +icq_Packet *icq_TCPCreateFileReqAck(icq_TCPLink *plink, WORD port); +icq_Packet *icq_TCPCreateFileReqCancel(icq_TCPLink *plink, WORD port); +icq_Packet *icq_TCPCreateFileReqRefuse(icq_TCPLink *plink, WORD port, + const char *reason); + +icq_Packet *icq_TCPCreateChatInfoPacket(icq_TCPLink *plink, const char *name, + DWORD foreground, DWORD background); +icq_Packet *icq_TCPCreateChatInfo2Packet(icq_TCPLink *plink, const char *name, + DWORD foreground, DWORD background); +icq_Packet *icq_TCPCreateChatFontInfoPacket(icq_TCPLink *plink); + +icq_Packet *icq_TCPCreateFile00Packet(DWORD num_files, DWORD total_bytes, DWORD speed, const char *name); +icq_Packet *icq_TCPCreateFile01Packet(DWORD speed, const char *name); +icq_Packet *icq_TCPCreateFile02Packet(const char *filename, DWORD filesize, DWORD speed); +icq_Packet *icq_TCPCreateFile03Packet(DWORD filesize, DWORD speed); +icq_Packet *icq_TCPCreateFile04Packet(DWORD filenum); +icq_Packet *icq_TCPCreateFile05Packet(DWORD speed); +icq_Packet *icq_TCPCreateFile06Packet(int length, void *data); + +icq_Packet *icq_UDPCreateStdPacket(ICQLINK *link, WORD cmd); +icq_Packet *icq_UDPCreateStdSeqPacket(ICQLINK *link, WORD cmd, WORD seq); + +#endif /* _ICQTCPPACKETS_H */ + +/* From `tcppackets.c': */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcp.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,639 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: tcp.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.36 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.35 2000/06/15 01:52:16 bills +added Cancel and Refuse functions for chat and file reqs, changed packet +sending code to use new icq_TCPLinkSendSeq function to elimitane duplicate +code, removed *Seq functions, renamed chat req functions + +Revision 1.34 2000/05/04 15:57:20 bills +Reworked file transfer notification, small bugfixes, and cleanups. + +Revision 1.33 2000/04/10 18:11:45 denis +ANSI cleanups. + +Revision 1.32 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.31 2000/04/06 16:38:04 denis +icq_*Send*Seq() functions with specified sequence number were added. + +Revision 1.30 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.29 2000/02/15 04:02:41 bills +warning cleanup + +Revision 1.28 2000/02/15 03:58:20 bills +use new icq_ChatRusConv_n function in icq_TCPSendChatData, +new icq_TCPSendChatData_n function + +Revision 1.27 2000/02/07 02:40:23 bills +new code for SOCKS connections, more cyrillic translations + +Revision 1.26 2000/01/20 19:59:15 bills +first implementation of sending file requests + +Revision 1.25 2000/01/16 21:28:24 bills +renamed icq_TCPAcceptFileReq to icq_AcceptFileRequest, moved file request +functions to new file session code + +Revision 1.24 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.23 1999/12/27 16:10:04 bills +fixed buy in icq_TCPAcceptFileReq, added icq_TCPFileSetSpeed + +Revision 1.22 1999/12/21 00:29:59 bills +moved _process_packet logic into tcplink::icq_TCPLinkProcessReceived, +removed unnecessary icq_TCPSendFile??Packet functions + +Revision 1.21 1999/12/14 03:31:48 bills +fixed double delete bug in _handle_ready_sockets, added code to implement +connect timeout + +Revision 1.20 1999/11/30 09:44:31 bills +added file session logic + +Revision 1.19 1999/09/29 20:07:12 bills +cleanups, moved connect logic from _handle_ready_sockets to +icq_TCPLinkOnConnect, tcp_link->icq_TCPLink + +Revision 1.18 1999/09/29 17:08:48 denis +Cleanups. + +Revision 1.17 1999/07/18 20:19:56 bills +added better log messages + +Revision 1.16 1999/07/16 15:45:56 denis +Cleaned up. + +Revision 1.15 1999/07/16 12:14:13 denis +tcp_packet* functions renamed to icq_Packet* +Cleaned up. + +Revision 1.14 1999/07/12 15:13:34 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.13 1999/07/03 06:33:49 lord +. byte order conversion macros added +. some compilation warnings removed + +Revision 1.12 1999/06/30 13:52:22 bills +implemented non-blocking connects + +Revision 1.11 1999/05/03 21:41:26 bills +initial file xfer support added- untested + +Revision 1.10 1999/04/29 09:35:41 denis +Cleanups, warning removed + +Revision 1.9 1999/04/17 19:30:50 bills +_major_ restructuring. all tcp sockets (including listening sockets) are +kept in global linked list, icq_TCPLinks. accept and listen functions +moved to tcplink.c. changed return values of Send* functions to DWORD. + +Revision 1.8 1999/04/14 14:57:05 denis +Cleanups for "strict" compiling (-ansi -pedantic) +Parameter port added to function icq_TCPCreateListeningSocket() + +*/ + +/* + Peer-to-peer ICQ protocol implementation + + Uses version 2 of the ICQ protocol + + Thanks to Douglas F. McLaughlin and many others for + packet details (see tcp02.txt) + +*/ + +#include <stdlib.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include <fcntl.h> +#include <stdarg.h> +#include <errno.h> + +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock.h> +#else +#include <sys/socket.h> +#endif + +#include <sys/stat.h> + +#ifndef _WIN32 +#include <sys/time.h> +#endif + +#include "icqtypes.h" +#include "icqlib.h" + +#include "tcp.h" +#include "stdpackets.h" +#include "list.h" +#include "tcplink.h" +#include "chatsession.h" +#include "filesession.h" + +/** + Initializes structures necessary for TCP use. Not required by user + programs. + + \return true on error +*/ + +int icq_TCPInit(ICQLINK *link) +{ + icq_TCPLink *plink; + + /* allocate lists */ + link->icq_TCPLinks=list_new(); + link->icq_ChatSessions=list_new(); + link->icq_FileSessions=list_new(); + + /* only the main listening socket gets created upon initialization - + * the other two are created when necessary */ + plink=icq_TCPLinkNew( link ); + icq_TCPLinkListen(plink); + link->icq_TCPSrvPort=ntohs(plink->socket_address.sin_port); + + /* reset tcp sequence number */ + link->icq_TCPSequence=0xfffffffe; + + return 0; +} + +void icq_TCPDone(ICQLINK *link) +{ + /* close and deallocate all tcp links, this will also close any attached + * file or chat sessions */ + list_delete(link->icq_TCPLinks, icq_TCPLinkDelete); + list_delete(link->icq_ChatSessions, icq_ChatSessionDelete); + list_delete(link->icq_FileSessions, icq_FileSessionDelete); +} + +/* helper function for icq_TCPMain */ +int _generate_fds(void *p, va_list data) +{ + icq_TCPLink *plink=(icq_TCPLink *)p; + ICQLINK *icqlink = plink->icqlink; + + (void)data; + + if(plink->socket>-1) + { + int socket=plink->socket; + + FD_SET(socket, &icqlink->TCP_readfds); + + /* we only care about writing if socket is trying to connect */ + if(plink->mode & TCP_LINK_MODE_CONNECTING) + { + if(plink->mode & (TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_CONNSTATUS)) + FD_SET(socket, &icqlink->TCP_readfds); + else + FD_SET(socket, &icqlink->TCP_writefds); + } + + if(socket+1>icqlink->TCP_maxfd) + icqlink->TCP_maxfd=socket+1; + } + + return 0; /* traverse the entire list */ +} + +/* helper function for icq_TCPMain */ +int _handle_ready_sockets(void *p, va_list data) +{ + icq_TCPLink *plink=(icq_TCPLink *)p; + ICQLINK *icqlink = plink->icqlink; + int socket=plink->socket; + + (void)data; + + /* handle connecting sockets */ + if (plink->mode & TCP_LINK_MODE_CONNECTING) + { + if(socket>-1 && (FD_ISSET(socket, &icqlink->TCP_writefds) || FD_ISSET(socket, &icqlink->TCP_readfds))) + { + icq_TCPLinkOnConnect(plink); + return 0; + } + + if((time(0L) - plink->connect_time) > TCP_LINK_CONNECT_TIMEOUT) + { + icq_TCPLinkClose(plink); + return 0; + } + } + + /* handle ready for read sockets- either a connection is waiting on * + * the listen sockets or data is ready to be read */ + if(socket>-1 && FD_ISSET(socket, &icqlink->TCP_readfds)) + { + if(plink->mode & TCP_LINK_MODE_LISTEN) + (void)icq_TCPLinkAccept(plink); + else { + + int result=icq_TCPLinkOnDataReceived(plink); + + /* close the link if there was a receive error or if * + * the remote end has closed the connection */ + if (result < 1) + icq_TCPLinkClose(plink); + + } + } + + return 0; /* traverse the entire list */ +} + +/* helper function for icq_TCPMain */ +int _process_links(void *p, va_list data) +{ + icq_TCPLink *plink=(icq_TCPLink *)p; + + (void)data; + + /* receive any packets watiting on the link */ + icq_TCPLinkProcessReceived(plink); + + /* if this a currently sending file link, send data! */ + if(plink->type==TCP_LINK_FILE) { + icq_FileSession *psession=plink->session; + if(psession && psession->status==FILE_STATUS_SENDING) + icq_FileSessionSendData(psession); + } + + return 0; /* traverse entire list */ +} + +void icq_TCPMain(ICQLINK *link) +{ + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 0; + + link->TCP_maxfd = 0; + FD_ZERO(&link->TCP_readfds); + FD_ZERO(&link->TCP_writefds); + + /* generate the fd sets for all open tcp links */ + (void)list_traverse(link->icq_TCPLinks, _generate_fds); + + /* determine which sockets require maintenance */ + select(link->TCP_maxfd, &link->TCP_readfds, &link->TCP_writefds, 0, &tv); + + /* call icq_TCPLinkOnDataReceived for any sockets with ready data, + * send all packets on send queue if socket has connected, and + * accept() from any listening sockets with pending connections */ + (void)list_traverse(link->icq_TCPLinks, _handle_ready_sockets, 0, 0); + + /* process all packets waiting for each TCPLink */ + (void)list_traverse(link->icq_TCPLinks, _process_links, 0, 0); +} + +icq_TCPLink *icq_TCPCheckLink(ICQLINK *link, DWORD uin, int type) +{ + icq_TCPLink *plink=icq_FindTCPLink(link, uin, type); + + if(!plink) + { + plink=icq_TCPLinkNew( link ); + if(type==TCP_LINK_MESSAGE) + icq_TCPLinkConnect(plink, uin, 0); + } + + return plink; + +} + +DWORD icq_TCPSendMessage(ICQLINK *link, DWORD uin, const char *message) +{ + icq_TCPLink *plink; + icq_Packet *p; + DWORD sequence; + char data[512] ; + + strncpy(data,message,512) ; + icq_RusConv("kw", data) ; + + plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + /* create and send the message packet */ + p=icq_TCPCreateMessagePacket(plink, (unsigned char *)data); + sequence=icq_TCPLinkSendSeq(plink, p, 0); + +#ifdef TCP_PACKET_TRACE + printf("message packet sent to uin %lu { sequence=%lx }\n", uin, p->id); +#endif + + return sequence; +} + +DWORD icq_TCPSendURL(ICQLINK *link, DWORD uin, const char *message, const char *url) +{ + icq_TCPLink *plink; + icq_Packet *p; + DWORD sequence; + char data[512]; + + plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + strncpy(data, message, 512); + data[511] = '\0'; + icq_RusConv("kw", data); + + /* create and send the url packet */ + p=icq_TCPCreateURLPacket(plink, data, url); + sequence=icq_TCPLinkSendSeq(plink, p, 0); + +#ifdef TCP_PACKET_TRACE + printf("url packet queued for uin %lu { sequence=%lx }\n", uin, p->id); +#endif + + return sequence; +} + +DWORD icq_SendChatRequest(ICQLINK *link, DWORD uin, const char *message) +{ + icq_TCPLink *plink; + icq_Packet *p; + DWORD sequence; + char data[512]; + + plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + strncpy(data, message, 512); + data[511] = '\0'; + icq_RusConv("kw", data); + + /* create and send the url packet */ + p=icq_TCPCreateChatReqPacket(plink, (unsigned char *)data); + sequence=icq_TCPLinkSendSeq(plink, p, 0); + +#ifdef TCP_PACKET_TRACE + printf("chat req packet sent to uin %lu { sequence=%lx }\n", uin, p->id); +#endif + + return sequence; +} + +unsigned long icq_SendFileRequest(ICQLINK *link, unsigned long uin, + const char *message, char **files) +{ + icq_TCPLink *plink; + icq_FileSession *pfile; + icq_Packet *p; + unsigned long sequence; + char filename[64]; + char data[512]; + + plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + /* create the file session, this will be linked to the incoming icq_TCPLink + * in icq_HandleFileAck */ + pfile=icq_FileSessionNew(link); + pfile->remote_uin=uin; + pfile->files=files; + pfile->direction=FILE_STATUS_SENDING; + + /* count the number and size of the files */ + pfile->total_files=0; + while(*files) { + struct stat file_status; + + if(stat(*files, &file_status)==0) { + pfile->total_files++; + pfile->total_bytes+=file_status.st_size; + } + files++; + } + + strncpy(filename, *(pfile->files), 64); + + strncpy(data, message, 512); + data[511] = '\0'; + icq_RusConv("kw", data); + + /* create and send the file req packet */ + p=icq_TCPCreateFileReqPacket(plink, (char *)data, filename, + pfile->total_bytes); + sequence=icq_TCPLinkSendSeq(plink, p, 0); + pfile->id=sequence; + +#ifdef TCP_PACKET_TRACE + printf("file req packet sent to uin %lu { sequence=%lx }\n", uin, p->id); +#endif + + return sequence; +} + +void icq_AcceptChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence) +{ + icq_TCPLink *pmessage, *plisten; + icq_ChatSession *pchat; + icq_Packet *p; + + pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + /* create the chat listening socket if necessary */ + if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_CHAT))) + { + plisten=icq_TCPLinkNew( link ); + plisten->type=TCP_LINK_CHAT; + icq_TCPLinkListen(plisten); + } + + /* create the chat session, this will be linked to the incoming icq_TCPLink + * in TCPProcessHello */ + pchat=icq_ChatSessionNew(link); + pchat->id=sequence; + pchat->remote_uin=uin; + + /* create and send the ack packet */ + p=icq_TCPCreateChatReqAck(pmessage, + ntohs(plisten->socket_address.sin_port)); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); + +#ifdef TCP_PACKET_TRACE + printf("chat req ack sent to uin %lu { sequence=%lx }\n", uin, sequence); +#endif +} + +void icq_TCPSendChatData(ICQLINK *link, DWORD uin, const char *data) +{ + icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); + char data1[512]; + int data1_len; + + if(!plink) + return; + + strncpy(data1,data,512) ; + data1[511] = '\0'; + data1_len = strlen(data); + icq_ChatRusConv_n("kw", data1, data1_len); + + send(plink->socket, data1, data1_len, 0); + +} + +void icq_TCPSendChatData_n(ICQLINK *link, DWORD uin, const char *data, int len) +{ + icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); + char *data1; + + if(!plink) + return; + + data1 = (char *)malloc(len); + memcpy(data1, data, len); + icq_ChatRusConv_n("kw", data1, len); + + send(plink->socket, data1, len, 0); + +} + +void icq_TCPCloseChat(ICQLINK *link, unsigned long uin) +{ + icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); + + if(plink) + icq_TCPLinkClose(plink); + +} + +icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, DWORD uin, + unsigned long sequence) +{ + icq_TCPLink *pmessage, *plisten; + icq_FileSession *pfile; + icq_Packet *p; + + pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + + /* create the file listening socket if necessary */ + if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_FILE))) + { + plisten=icq_TCPLinkNew( link ); + plisten->type=TCP_LINK_FILE; + icq_TCPLinkListen(plisten); + } + + /* create the file session, this will be linked to the incoming icq_TCPLink + * in TCPProcessHello */ + pfile=icq_FileSessionNew(link); + pfile->id=sequence; + pfile->remote_uin=uin; + pfile->direction=FILE_STATUS_RECEIVING; + icq_FileSessionSetStatus(pfile, FILE_STATUS_LISTENING); + + /* create and send the ack packet */ + p=icq_TCPCreateFileReqAck(pmessage, + ntohs(plisten->socket_address.sin_port)); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); + +#ifdef TCP_PACKET_TRACE + printf("file req ack sent to uin %lu { sequence=%lx }\n", uin, sequence); +#endif + + return pfile; + +} + +void icq_RefuseFileRequest(ICQLINK *link, DWORD uin, + unsigned long sequence, const char *reason) +{ + icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + icq_Packet *p; + + /* create and send the refuse packet */ + p=icq_TCPCreateFileReqRefuse(pmessage, + ntohs(pmessage->socket_address.sin_port), reason); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); + +#ifdef TCP_PACKET_TRACE + printf("file req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n", + uin, sequence, reason); +#endif + +} + +void icq_CancelFileRequest(ICQLINK *link, DWORD uin, unsigned long sequence) +{ + icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + icq_FileSession *psession=icq_FindFileSession(link, uin, sequence); + icq_Packet *p; + + if (psession) + icq_FileSessionClose(psession); + + /* create and send the cancel packet */ + p=icq_TCPCreateFileReqCancel(pmessage, + ntohs(pmessage->socket_address.sin_port)); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); +#ifdef TCP_PACKET_TRACE + printf("file req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence); +#endif + +} + +void icq_RefuseChatRequest(ICQLINK *link, DWORD uin, + unsigned long sequence, const char *reason) +{ + icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + icq_Packet *p; + + /* create and send the refuse packet */ + p=icq_TCPCreateChatReqRefuse(pmessage, + ntohs(pmessage->socket_address.sin_port), reason); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); + +#ifdef TCP_PACKET_TRACE + printf("chat req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n", + uin, sequence, reason); +#endif + +} + +void icq_CancelChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence) +{ + icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE); + icq_FileSession *psession=icq_FindFileSession(link, uin, sequence); + icq_Packet *p; + + if (psession) + icq_FileSessionClose(psession); + + /* create and send the cancel packet */ + p=icq_TCPCreateChatReqCancel(pmessage, + ntohs(pmessage->socket_address.sin_port)); + (void)icq_TCPLinkSendSeq(pmessage, p, sequence); + +#ifdef TCP_PACKET_TRACE + printf("chat req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence); +#endif + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcp.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,42 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +#ifndef _ICQTCP_H +#define _ICQTCP_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icq.h" +#include "tcplink.h" +#include "util.h" + +/* initialize icq_TCPSocket and icq_TCPSocketAddress + * returns < 0 on failure */ +int icq_TCPInit(ICQLINK *link); + +/* close icq_TCPSocket, internal cleanup */ +void icq_TCPDone(ICQLINK *link); + +int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink); +void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink); +void icq_TCPProcessChatPacket(icq_Packet *p, icq_TCPLink *plink); +void icq_TCPProcessFilePacket(icq_Packet *p, icq_TCPLink *plink); + +/* Debugging */ +/* trace packet process results */ +/* #define TCP_PROCESS_TRACE */ + +/* trace sent and received icq packets */ +/* #define TCP_PACKET_TRACE */ + +/* trace raw sent and received packet data */ +/* #define TCP_RAW_TRACE */ + +/* trace recv buffer in tcplink.c*/ +#undef TCP_BUFFER_TRACE + +/* trace queueing operations in list.c */ +#undef TCP_QUEUE_TRACE + +#endif /* _ICQTCP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcpchathandle.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,271 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: tcpchathandle.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.8 2000/07/24 03:10:08 bills +added support for real nickname during TCP transactions like file and +chat, instead of using Bill all the time (hmm, where'd I get that from? :) + +Revision 1.7 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.6 2000/05/04 15:57:20 bills +Reworked file transfer notification, small bugfixes, and cleanups. + +Revision 1.5 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.4 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.3 2000/02/07 02:54:45 bills +warning cleanups. + +Revision 1.2 2000/02/07 02:43:37 bills +new code for special chat functions (background, fonts, etc) + +Revision 1.1 1999/09/29 19:47:21 bills +reworked chat/file handling. fixed chat. (it's been broke since I put +non-blocking connects in) + +*/ + +#include <time.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include <stdlib.h> + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" + +#include "stdpackets.h" +#include "tcplink.h" +#include "chatsession.h" + +void icq_HandleChatAck(icq_TCPLink *plink, icq_Packet *p, int port) +{ + icq_TCPLink *pchatlink; + icq_ChatSession *pchat; + icq_Packet *p2; + + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0); + pchatlink=icq_TCPLinkNew(plink->icqlink); + pchatlink->type=TCP_LINK_CHAT; + pchatlink->id=p->id; + + pchat=icq_ChatSessionNew(plink->icqlink); + pchat->id=p->id; + pchat->remote_uin=plink->remote_uin; + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_CONNECTING); + icq_TCPLinkConnect(pchatlink, plink->remote_uin, port); + + pchatlink->session=pchat; + + p2=icq_TCPCreateChatInfoPacket(pchatlink, plink->icqlink->icq_Nick, + 0x00ffffff, 0x00000000); + icq_TCPLinkSend(pchatlink, p2); + +} + +void icq_HandleChatHello(icq_TCPLink *plink) +{ + + /* once the hello packet has been processed and we know which uin this + * link is for, we can link up with a chat session */ + icq_ChatSession *pchat=icq_FindChatSession(plink->icqlink, + plink->remote_uin); + + if(pchat) + { + plink->id=pchat->id; + plink->session=pchat; + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_WAIT_NAME); + + } else { + + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, + "unexpected chat hello received from %d, closing link\n", + plink->remote_uin); + icq_TCPLinkClose(plink); + } + +} + +void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id) +{ +#ifdef TCP_PACKET_TRACE + printf("chat request packet received from %lu { sequence=%lx, message=%s }\n", + uin, id, message); +#endif /* TCP_PACKET_TRACE */ + + if(link->icq_RecvChatReq) { + + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + + (*link->icq_RecvChatReq)(link, uin, ptime->tm_hour, ptime->tm_min, + ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, message, id); + + /* don't send an acknowledgement to the remote client! + * GUI is responsible for sending acknowledgement once user accepts + * or denies using icq_TCPSendChatAck */ + } +} + +void icq_TCPChatUpdateFont(icq_TCPLink *plink, const char *font, WORD encoding, DWORD style, DWORD size) +{ + int packet_len, fontlen; + char *buffer; + if(!plink->icqlink->icq_RequestNotify) + return; + buffer = malloc(packet_len = (2 + (fontlen = strlen(font) + 1)) + 2 + 1 + (4+1)*2); + buffer[0] = '\x11'; + *((DWORD *)&buffer[1]) = style; + buffer[5] = '\x12'; + *((DWORD *)&buffer[6]) = size; + buffer[10] = '\x10'; + *((WORD *)&buffer[11]) = fontlen; + strcpy(&buffer[13], font); + icq_RusConv("wk", &buffer[13]); + *((WORD *)&buffer[13 + fontlen]) = encoding; + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, packet_len, buffer); + free(buffer); +} + +void icq_TCPChatUpdateColors(icq_TCPLink *plink, DWORD foreground, DWORD background) +{ + char buffer[10]; + + if(!plink->icqlink->icq_RequestNotify) + return; + buffer[0] = '\x00'; + *((DWORD *)&buffer[1]) = foreground; + buffer[5] = '\x01'; + *((DWORD *)&buffer[6]) = background; + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, + sizeof(buffer), buffer); +} + +void icq_TCPProcessChatPacket(icq_Packet *p, icq_TCPLink *plink) +{ + DWORD code; + DWORD remote_uin; + DWORD ip1, ip2; + DWORD fg, bg, fontstyle, fontsize; + WORD port1, encoding; + icq_Packet *presponse; + icq_ChatSession *pchat=(icq_ChatSession *)plink->session; + const char *font, *user; + + icq_PacketBegin(p); + + code=icq_PacketRead32(p); + remote_uin=icq_PacketRead32(p); + + if(code==0x00000006 || code==0x00070004) + { + font = (char *)NULL; + encoding = 0; + fontstyle = 0; + fontsize = 0; + if(code == 0x00070004) + { + ip1 = icq_PacketRead32(p); + ip2 = icq_PacketRead32(p); + icq_PacketRead8(p); + port1 = icq_PacketRead16(p); + fontsize = icq_PacketRead32(p); + fontstyle = icq_PacketRead32(p); + font = icq_PacketReadString(p); + encoding = icq_PacketRead16(p); + } + else + { + ip1 = icq_PacketRead32(p); + ip2 = icq_PacketRead32(p); + port1 = icq_PacketRead16(p); + icq_PacketRead8(p); + fontsize = icq_PacketRead32(p); + fontstyle = icq_PacketRead32(p); + font = icq_PacketReadString(p); + encoding = icq_PacketRead16(p); + } + if(font) + icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize); + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_READY); + plink->mode|=TCP_LINK_MODE_RAW; + } + else + if(remote_uin>0xffffff00) + { + remote_uin=icq_PacketRead32(p); + user = icq_PacketReadString(p); + icq_PacketRead16(p); /* Unknown */; + fg = icq_PacketRead32(p); + bg = icq_PacketRead32(p); + icq_TCPChatUpdateColors(plink, fg, bg); + + presponse=icq_TCPCreateChatInfo2Packet(plink, plink->icqlink->icq_Nick, + 0x00ffffff, 0x00000000); + icq_PacketSend(presponse, plink->socket); + icq_PacketDelete(presponse); + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_WAIT_FONT); + } + else + { + user = icq_PacketReadString(p); + fg = icq_PacketRead32(p); + bg = icq_PacketRead32(p); + icq_TCPChatUpdateColors(plink, fg, bg); + font = (char *)NULL; + encoding = 0; + fontstyle = 0; + fontsize = 0; + if((code = icq_PacketRead32(p)) == 0x00070004) + { + icq_PacketRead32(p); + ip1 = icq_PacketRead32(p); + ip2 = icq_PacketRead32(p); + icq_PacketRead8(p); + port1 = icq_PacketRead16(p); + fontsize = icq_PacketRead32(p); + fontstyle = icq_PacketRead32(p); + font = icq_PacketReadString(p); + encoding = icq_PacketRead16(p); + } + else if(code == 0x00000006) + { + icq_PacketRead32(p); + ip1 = icq_PacketRead32(p); + ip2 = icq_PacketRead32(p); + port1 = icq_PacketRead16(p); + icq_PacketRead8(p); + fontsize = icq_PacketRead32(p); + fontstyle = icq_PacketRead32(p); + font = icq_PacketReadString(p); + encoding = icq_PacketRead16(p); + } + if(font) + icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize); + presponse=icq_TCPCreateChatFontInfoPacket(plink); + icq_PacketSend(presponse, plink->socket); + icq_PacketDelete(presponse); + /* notify app that chat connection has been established */ + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_READY); + plink->mode|=TCP_LINK_MODE_RAW; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcpfilehandle.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,295 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: tcpfilehandle.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.15 2000/07/24 03:10:08 bills +added support for real nickname during TCP transactions like file and +chat, instead of using Bill all the time (hmm, where'd I get that from? :) + +Revision 1.14 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.13 2000/06/25 16:35:08 denis +'\n' was added at the end of log messages. + +Revision 1.12 2000/06/15 01:52:59 bills +fixed bug: sending file sessions would freeze if remote side changed speed + +Revision 1.11 2000/05/04 15:57:20 bills +Reworked file transfer notification, small bugfixes, and cleanups. + +Revision 1.10 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.9 2000/04/10 18:11:45 denis +ANSI cleanups. + +Revision 1.8 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.7 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.6 2000/01/20 20:06:00 bills +removed debugging printfs + +Revision 1.5 2000/01/20 19:59:15 bills +first implementation of sending file requests + +Revision 1.4 2000/01/16 21:29:31 bills +added code so icq_FileSessions now keep track of the tcplink to which +they are attached + +Revision 1.3 1999/12/21 00:30:15 bills +added more file transfer logic to write file to disk + +Revision 1.2 1999/11/30 09:47:04 bills +added icq_HandleFileHello + +Revision 1.1 1999/09/29 19:47:21 bills +reworked chat/file handling. fixed chat. (it's been broke since I put +non-blocking connects in) + +*/ + +#include <time.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#ifdef _MSVC_ +#include <io.h> +#define open _open +#define close _close +#define read _read +#define write _write +#endif + +#include <errno.h> + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" + +#include "tcp.h" +#include "icqpacket.h" +#include "stdpackets.h" +#include "tcplink.h" +#include "filesession.h" + +void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, + const char *filename, unsigned long filesize, DWORD id) +{ +#ifdef TCP_PACKET_TRACE + printf("file request packet received from %lu { sequence=%lx, message=%s }\n", + uin, id, message); +#endif + + if(link->icq_RecvFileReq) { + + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + + (*link->icq_RecvFileReq)(link, uin, ptime->tm_hour, ptime->tm_min, + ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, message, + filename, filesize, id); + + /* don't send an acknowledgement to the remote client! + * GUI is responsible for sending acknowledgement once user accepts + * or denies using icq_TCPSendFileAck */ + } +} + +void icq_TCPProcessFilePacket(icq_Packet *p, icq_TCPLink *plink) +{ + icq_FileSession *psession=(icq_FileSession *)plink->session; + BYTE type; + DWORD num_files; + DWORD total_bytes; + DWORD speed; + DWORD filesize; + const char *name; + int result; + + icq_Packet *presponse; + + icq_PacketBegin(p); + + type=icq_PacketRead8(p); + + switch(type) + { + case 0x00: + (void)icq_PacketRead32(p); + num_files=icq_PacketRead32(p); + total_bytes=icq_PacketRead32(p); + speed=icq_PacketRead32(p); + name=icq_PacketReadString(p); + psession->total_files=num_files; + psession->total_bytes=total_bytes; + psession->current_speed=speed; + icq_FileSessionSetHandle(psession, name); + icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED); + + /* respond */ + presponse=icq_TCPCreateFile01Packet(speed, plink->icqlink->icq_Nick); + + icq_TCPLinkSend(plink, presponse); +#ifdef TCP_PACKET_TRACE + printf("file 01 packet sent to uin %lu\n", plink->remote_uin); +#endif + + break; + + case 0x01: + speed=icq_PacketRead32(p); + name=icq_PacketReadString(p); + psession->current_speed=speed; + icq_FileSessionSetHandle(psession, name); + icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED); + + /* respond */ + icq_FileSessionPrepareNextFile(psession); + presponse=icq_TCPCreateFile02Packet(psession->current_file, + psession->current_file_size, psession->current_speed); + + icq_TCPLinkSend(plink, presponse); +#ifdef TCP_PACKET_TRACE + printf("file 02 packet sent to uin %lu\n", plink->remote_uin); +#endif + break; + + case 0x02: + /* when files are skipped + psession->total_transferred_bytes+= + (psession->current_file_size-psession->current_file_progress); + */ + + (void)icq_PacketRead8(p); + name=icq_PacketReadString(p); + (void)icq_PacketReadString(p); + filesize=icq_PacketRead32(p); + (void)icq_PacketRead32(p); + speed=icq_PacketRead32(p); + icq_FileSessionSetCurrentFile(psession, name); + psession->current_file_size=filesize; + psession->current_speed=speed; + psession->current_file_num++; + icq_FileSessionSetStatus(psession, FILE_STATUS_NEXT_FILE); + + /* respond */ + presponse=icq_TCPCreateFile03Packet(psession->current_file_progress, + speed); + + icq_TCPLinkSend(plink, presponse); +#ifdef TCP_PACKET_TRACE + printf("file 03 packet sent to uin %lu\n", plink->remote_uin); +#endif + break; + + case 0x03: + filesize=icq_PacketRead32(p); + (void)icq_PacketRead32(p); + speed=icq_PacketRead32(p); + psession->current_file_progress=filesize; + psession->total_transferred_bytes+=filesize; + psession->current_speed=speed; + + icq_FileSessionSetStatus(psession, FILE_STATUS_NEXT_FILE); + icq_FileSessionSetStatus(psession, FILE_STATUS_SENDING); + break; + + case 0x04: + (void)icq_PacketRead32(p); + icq_FileSessionSetStatus(psession, FILE_STATUS_STOP_FILE); + break; + + case 0x05: + speed=icq_PacketRead32(p); + psession->current_speed=speed; + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, + ICQ_NOTIFY_FILE, FILE_STATUS_NEW_SPEED, 0); + break; + + case 0x06: + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_FILEDATA, + p->length-sizeof(BYTE), p->data+sizeof(BYTE)); + icq_FileSessionSetStatus(psession, FILE_STATUS_RECEIVING); + result=write(psession->current_fd, p->data+sizeof(BYTE), p->length-sizeof(BYTE)); + psession->current_file_progress+=p->length-sizeof(BYTE); + psession->total_transferred_bytes+=p->length-sizeof(BYTE); + break; + + default: + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown file packet type %d!\n", type); + + } +} + +void icq_HandleFileHello(icq_TCPLink *plink) +{ + + /* once the hello packet has been processed and we know which uin this + * link is for, we can link up with a file session */ + icq_FileSession *pfile=icq_FindFileSession(plink->icqlink, + plink->remote_uin, 0); + + if(pfile) + { + plink->id=pfile->id; + plink->session=pfile; + pfile->tcplink=plink; + icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTED); + + } else { + + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, + "unexpected file hello received from %d, closing link\n", + plink->remote_uin); + icq_TCPLinkClose(plink); + } + +} + +void icq_HandleFileAck(icq_TCPLink *plink, icq_Packet *p, int port) +{ + icq_TCPLink *pfilelink; + icq_FileSession *pfile; + icq_Packet *p2; + + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0); + pfilelink=icq_TCPLinkNew(plink->icqlink); + pfilelink->type=TCP_LINK_FILE; + pfilelink->id=p->id; + + /* once the ack packet has been processed, link up with the file session */ + pfile=icq_FindFileSession(plink->icqlink, plink->remote_uin, 0); + + pfile->tcplink=pfilelink; + pfilelink->id=pfile->id; + + if (plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, pfile->id, + ICQ_NOTIFY_FILESESSION, sizeof(icq_FileSession), pfile); + + icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTING); + icq_TCPLinkConnect(pfilelink, plink->remote_uin, port); + + pfilelink->session=pfile; + + p2=icq_TCPCreateFile00Packet( pfile->total_files, + pfile->total_bytes, pfile->current_speed, plink->icqlink->icq_Nick); + icq_TCPLinkSend(pfilelink, p2); + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcphandle.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,366 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: tcphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.12 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.11 2000/06/25 16:36:16 denis +'\n' was added at the end of log messages. + +Revision 1.10 2000/05/04 15:57:20 bills +Reworked file transfer notification, small bugfixes, and cleanups. + +Revision 1.9 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.8 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.7 2000/01/20 20:06:00 bills +removed debugging printfs + +Revision 1.6 2000/01/20 19:59:15 bills +first implementation of sending file requests + +Revision 1.5 1999/11/30 09:51:42 bills +more file xfer logic added + +Revision 1.4 1999/11/11 15:10:30 guruz +- Added Base for Webpager Messages. Please type "make fixme" +- Removed Segfault when kicq is started the first time + +Revision 1.3 1999/10/01 02:28:51 bills +icq_TCPProcessHello returns something now :) + +Revision 1.2 1999/10/01 00:49:20 lord +some compilation problems are fixed. + +Revision 1.1 1999/09/29 19:47:21 bills +reworked chat/file handling. fixed chat. (it's been broke since I put +non-blocking connects in) + +Revision 1.15 1999/07/16 15:45:59 denis +Cleaned up. + +Revision 1.14 1999/07/16 12:10:10 denis +tcp_packet* functions renamed to icq_Packet* +Cleaned up. + +Revision 1.13 1999/07/12 15:13:41 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.12 1999/06/30 13:51:25 bills +cleanups + +Revision 1.11 1999/05/03 21:41:30 bills +initial file xfer support added- untested + +Revision 1.10 1999/04/29 09:36:06 denis +Cleanups, warning removed + +Revision 1.9 1999/04/17 19:40:33 bills +reworked code to use icq_TCPLinks instead of icq_ContactItem entries. +modified ProcessChatPacket to negotiate both sending and receiving chat +requests properly. + +Revision 1.8 1999/04/14 15:12:02 denis +Cleanups for "strict" compiling (-ansi -pedantic) +icq_ContactItem parameter added to function icq_TCPOnMessageReceived() +Segfault fixed on spoofed messages. + +*/ + +#include <time.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" + +#include "tcp.h" +#include "stdpackets.h" +#include "tcplink.h" + +void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink); +void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); +void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); +void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, + const char *filename, unsigned long filesize, DWORD id); +void icq_TCPProcessAck(ICQLINK *link, icq_Packet *p); +void icq_HandleChatAck(icq_TCPLink *plink, icq_Packet *p, int port); +void icq_HandleChatHello(icq_TCPLink *plink); +void icq_HandleFileHello(icq_TCPLink *plink); +void icq_HandleFileAck(icq_TCPLink *plink, icq_Packet *p, int port); + +void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink) +{ + DWORD uin; + WORD version; + WORD command; + WORD type; + WORD status; + DWORD command_type; + DWORD filesize = 0; + DWORD port = 0; + + const char *message; + const char *filename = 0; + + icq_PacketBegin(p); + (void)icq_PacketRead32(p); + version=icq_PacketRead16(p); + command=icq_PacketRead16(p); + (void)icq_PacketRead16(p); + + uin=icq_PacketRead32(p); + type=icq_PacketRead16(p); + message=icq_PacketReadString(p); + (void)icq_PacketRead32(p); + (void)icq_PacketRead32(p); + (void)icq_PacketRead32(p); + (void)icq_PacketRead8(p); + status=icq_PacketRead16(p); + command_type=icq_PacketRead16(p); + + switch(type) + { + case ICQ_TCP_MSG_MSG: + case ICQ_TCP_MSG_URL: + p->id=icq_PacketRead32(p); + break; + + case ICQ_TCP_MSG_CHAT: + (void)icq_PacketReadString(p); + (void)icq_PacketRead16(p); + (void)icq_PacketRead16(p); + port=icq_PacketRead32(p); + p->id=icq_PacketRead32(p); + break; + + case ICQ_TCP_MSG_FILE: + (void)icq_PacketRead16(p); + (void)icq_PacketRead16(p); + filename=icq_PacketReadString(p); + filesize=icq_PacketRead32(p); + port=icq_PacketRead32(p); + p->id=icq_PacketRead32(p); + break; + + default: + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message packet, type %x\n", type); + } + +#ifdef TCP_PROCESS_TRACE + printf("packet processed from uin: %lu:\n", uin); + printf(" command: %x\ttype: %x\n", command, type); + printf(" status: %x\tcommand_type: %x\n", status, (int)command_type); + printf(" message %s\n", message); + printf(" id: %x\n", (int)p->id); +#endif + + switch(command) + { + case ICQ_TCP_MESSAGE: + switch(type) + { + case ICQ_TCP_MSG_MSG: + icq_TCPOnMessageReceived(plink->icqlink, uin, message, p->id, plink); + break; + + case ICQ_TCP_MSG_URL: + icq_TCPOnURLReceived(plink->icqlink, uin, message, p->id); + break; + + case ICQ_TCP_MSG_CHAT: + icq_TCPOnChatReqReceived(plink->icqlink, uin, message, p->id); + break; + + case ICQ_TCP_MSG_FILE: + icq_TCPOnFileReqReceived(plink->icqlink, uin, message, filename, filesize, p->id); + break; + + default: + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type); + break; + } + break; + + case ICQ_TCP_ACK: + switch(type) { + case ICQ_TCP_MSG_CHAT: + icq_HandleChatAck(plink, p, port); + break; + + case ICQ_TCP_MSG_FILE: + icq_HandleFileAck(plink, p, port); + break; + + case ICQ_TCP_MSG_MSG: + case ICQ_TCP_MSG_URL: + if(plink->icqlink->icq_RequestNotify) { + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", p->id); + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, + (void *)message); + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0); + } + break; + } + break; + + case ICQ_TCP_CANCEL: + /* icq_TCPProcessCancel(p); */ + break; + + default: + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, + "unknown packet command %d!\n", command); + } +} + +void icq_TCPProcessCancel(icq_Packet *p) +{ + (void)p; + +/* + find packet in queue + call notification function + remove packet from queue +*/ +} + +int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink) +{ + /* TCP Hello packet */ + BYTE code; /* 0xFF - init packet code */ + DWORD version; /* tcp version */ + DWORD remote_port; /* remote message listen port */ + DWORD remote_uin; /* remote uin */ + DWORD remote_ip; /* remote IP as seen by ICQ server */ + DWORD remote_real_ip; /* remote IP as seen by client */ + BYTE flags; /* tcp flags */ + DWORD remote_other_port; /* remote chat or file listen port */ + + icq_PacketBegin(p); + + code=icq_PacketRead8(p); + version=icq_PacketRead32(p); + + if (!(p->length>=26 && code==ICQ_TCP_HELLO)) + { + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, + "malformed hello packet received from %s:%d, closing link\n", + inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), + ntohs(plink->remote_address.sin_port)); + + icq_TCPLinkClose(plink); + return 0; + } + remote_port=icq_PacketRead32(p); + remote_uin=icq_PacketRead32(p); + remote_ip=icq_PacketRead32(p); + remote_real_ip=icq_PacketRead32(p); + flags=icq_PacketRead8(p); + remote_other_port=icq_PacketRead32(p); + + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "hello packet received from %lu { version=%d }\n", remote_uin, version); + + plink->remote_version=version; + plink->remote_uin=remote_uin; + plink->flags=flags; + plink->mode&=~TCP_LINK_MODE_HELLOWAIT; + + /* file and chat sessions require additional handling */ + if(plink->type==TCP_LINK_CHAT) icq_HandleChatHello(plink); + if(plink->type==TCP_LINK_FILE) icq_HandleFileHello(plink); + + return 1; +} + +void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink) +{ + char data[512] ; +#ifdef TCP_PACKET_TRACE + printf("tcp message packet received from %lu { sequence=%x }\n", + uin, (int)id); +#endif + + if(link->icq_RecvMessage) + { + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + icq_Packet *pack; + icq_TCPLink *preallink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); + + strncpy(data,message,512) ; + icq_RusConv("wk",data) ; + + (*link->icq_RecvMessage)(link, uin, ptime->tm_hour, ptime->tm_min, + ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, data); + + if(plink != preallink) + { +/* if(icq_SpoofedMessage) + (*icq_SpoofedMessage(uin, ...));*/ + } + + if(plink) + { + /* send an acknowledgement to the remote client */ + pack=icq_TCPCreateMessageAck(plink,0); + icq_PacketAppend32(pack, id); + icq_PacketSend(pack, plink->socket); +#ifdef TCP_PACKET_TRACE + printf("tcp message ack sent to uin %lu { sequence=%lx }\n", uin, id); +#endif + icq_PacketDelete(pack); + } + } +} + +void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id) +{ +#ifdef TCP_PACKET_TRACE + printf("tcp url packet received from %lu { sequence=%lx }\n", + uin, id); +#endif /*TCP_PACKET_TRACE*/ + + if(link->icq_RecvURL) { + + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + icq_Packet *pack; + char *pfe; + icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); + + /* the URL is split from the description by 0xFE */ + pfe=strchr(message, '\xFE'); + *pfe=0; + (*link->icq_RecvURL)(link, uin, ptime->tm_hour, ptime->tm_min, + ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, pfe+1, message); + + /* send an acknowledgement to the remote client */ + pack=icq_TCPCreateURLAck(plink,0); + icq_PacketAppend32(pack, id); + icq_PacketSend(pack, plink->socket); +#ifdef TCP_PACKET_TRACE + printf("tcp message ack sent to %lu { sequence=%lx }\n", uin, id); +#endif + icq_PacketDelete(pack); + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcplink.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,1014 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: tcplink.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.38 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.37 2000/06/15 01:53:17 bills +added icq_TCPLinkSendSeq function + +Revision 1.36 2000/05/04 15:57:20 bills +Reworked file transfer notification, small bugfixes, and cleanups. + +Revision 1.35 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.34 2000/04/10 18:11:45 denis +ANSI cleanups. + +Revision 1.33 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.32 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.31 2000/02/15 04:00:16 bills + new icq_ChatRusConv_n function + +Revision 1.30 2000/02/07 02:46:29 bills +implemented non-blocking TCP connects over SOCKS, cyrillic translation for chat + +Revision 1.29 2000/01/20 19:59:35 bills +fixed bug in icq_TCPLinkConnect that caused file/chat connection attempts +to go to the wrong port + +Revision 1.28 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.27 1999/12/27 16:13:29 bills +fixed bug in icq_TCPOnDataReceived, removed flags variable ;) + +Revision 1.26 1999/12/27 10:56:10 denis +Unused "flags" variable commented out. + +Revision 1.25 1999/12/21 00:30:53 bills +added icq_TCPLinkProcessReceived to support processing receive queue +before delete (packets used to get dropped in this instance, oops), +reworked icq_TCPLinkOnDataReceived to handle quick, large streams of data, +changed icq_TCPLinkOnConnect and *Accept to make all sockets non-blocking. + +Revision 1.24 1999/12/14 03:33:34 bills +icq_TCPLinkConnect now uses real_ip when our IP is same as remote IP to make +connection, added code to implement connect timeout + +Revision 1.23 1999/11/30 09:57:44 bills +buffer overflow check added, tcplinks will now close if buffer overflows. +increased icq_TCPLinkBufferSize to 4096 to support file transfer packets + +Revision 1.22 1999/11/29 17:15:51 denis +Absence of socklen_t type fixed. + +Revision 1.21 1999/10/01 00:49:21 lord +some compilation problems are fixed. + +Revision 1.20 1999/09/29 20:26:41 bills +ack forgot the args :) + +Revision 1.19 1999/09/29 20:21:45 bills +renamed denis' new function + +Revision 1.18 1999/09/29 20:11:29 bills +renamed tcp_link* to icq_TCPLink*. many cleanups, added icq_TCPLinkOnConnect + +Revision 1.17 1999/09/29 17:10:05 denis +TCP code SOCKS-ification. Not finished. + +Revision 1.16 1999/07/18 20:21:34 bills +fixed fail notification bug introduced during ICQLINK changes, changed to +use new byte-order functions & contact list functions, added better log +messages + +Revision 1.15 1999/07/16 15:45:57 denis +Cleaned up. + +Revision 1.14 1999/07/16 12:02:58 denis +tcp_packet* functions renamed to icq_Packet* +Cleaned up. + +Revision 1.13 1999/07/12 15:13:36 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.12 1999/07/03 06:33:51 lord +. byte order conversion macros added +. some compilation warnings removed + +Revision 1.11 1999/06/30 13:52:23 bills +implemented non-blocking connects + +Revision 1.10 1999/05/03 21:39:41 bills +removed exit calls + +Revision 1.9 1999/04/29 09:35:54 denis +Cleanups, warning removed + +Revision 1.8 1999/04/17 19:34:49 bills +fixed bug in icq_TCPLinkOnDataReceived, multiple packets that come in on +one recv call are now handled correctly. added icq_TCPLinkAccept and +icq_TCPLinkListen. started using mode and type structure entries. added +icq_TCPLinks list and icq_FindTCPLink function. changed received_queue and +send_queue to lists. + +Revision 1.7 1999/04/14 15:02:45 denis +Cleanups for "strict" compiling (-ansi -pedantic) + +Revision 1.6 1999/04/05 18:47:17 bills +initial chat support implemented + +Revision 1.5 1999/03/31 01:50:54 bills +wrapped up many tcp details- tcp code now handles incoming and outgoing +tcp messages and urls! + +Revision 1.4 1999/03/28 03:27:49 bills +fixed icq_TCPLinkConnect so it really connects to remote ip instead of +always my local test computer O:) + +Revision 1.3 1999/03/26 20:02:41 bills +fixed C++ comments, cleaned up + +Revision 1.2 1999/03/25 22:21:59 bills +added necessary includes + +Revision 1.1 1999/03/25 21:09:07 bills +tcp link functions +*/ + +#include <stdlib.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include <fcntl.h> +#include <stdarg.h> +#include <errno.h> +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock.h> +#define EINPROGRESS WSAEINPROGRESS +#define ENETUNREACH WSAENETUNREACH +#define ECONNREFUSED WSAECONNREFUSED +#define ETIMEDOUT WSAETIMEDOUT +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define EWOULDBLOCK WSAEWOULDBLOCK +#else +#include <sys/socket.h> +#include <netdb.h> +#endif + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "tcplink.h" +#include "stdpackets.h" +#include "util.h" +#include "tcp.h" +#include "errno.h" +#include "chatsession.h" +#include "filesession.h" + +icq_TCPLink *icq_TCPLinkNew(ICQLINK *link) +{ + icq_TCPLink *p=(icq_TCPLink *)malloc(sizeof(icq_TCPLink)); + + p->socket=-1; + p->icqlink=link; + p->mode=0; + p->session=0L; + p->type=TCP_LINK_MESSAGE; + p->buffer_count=0; + p->send_queue=list_new(); + p->received_queue=list_new(); + p->id=0; + p->remote_uin=0; + p->remote_version=0; + p->flags=0; + p->proxy_status = 0; + + if(p) + list_enqueue(link->icq_TCPLinks, p); + + return p; +} + +int _icq_TCPLinkDelete(void *pv, va_list data) +{ + icq_Packet *p=(icq_Packet *)pv; + ICQLINK *icqlink=va_arg(data, ICQLINK *); + + /* notify the app the packet didn't make it */ + if(p->id) + (*icqlink->icq_RequestNotify)(icqlink, p->id, ICQ_NOTIFY_FAILED, 0, 0); + + return 0; +} + +void icq_TCPLinkDelete(void *pv) +{ + icq_TCPLink *p=(icq_TCPLink *)pv; + + /* process anything left in the received queue */ + icq_TCPLinkProcessReceived(p); + + /* make sure we notify app that packets in send queue didn't make it */ + (void)list_traverse(p->send_queue, _icq_TCPLinkDelete, p->icqlink); + + /* destruct all packets still waiting on queues */ + list_delete(p->send_queue, icq_PacketDelete); + list_delete(p->received_queue, icq_PacketDelete); + + /* notify app if this was a chat or file xfer session and there is an + * id assigned */ + if((p->type==TCP_LINK_CHAT || p->type==TCP_LINK_FILE) && p->id) + if(p->icqlink->icq_RequestNotify) + (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0); + + /* if this is a chat or file link, delete the associated session as + * well, but make sure we unassociate ourself first so the session + * doesn't try to close us */ + if(p->session) + { + if(p->type==TCP_LINK_CHAT) + { + icq_ChatSession *psession=p->session; + /*psession->tcplink=0L;*/ + icq_ChatSessionClose(psession); + } + + if(p->type==TCP_LINK_FILE) { + icq_FileSession *psession=p->session; + psession->tcplink=0L; + icq_FileSessionClose(psession); + } + } + + /* close the socket after we notify app so app can read errno if necessary */ + if (p->socket > -1) + { +#ifdef _WIN32 + closesocket(p->socket); +#else + close(p->socket); +#endif + } + + free(p); +} + +void icq_TCPLinkClose(icq_TCPLink *plink) +{ + list_remove(plink->icqlink->icq_TCPLinks, plink); + icq_TCPLinkDelete(plink); +} + +int icq_TCPLinkProxyConnect(icq_TCPLink *plink, DWORD uin, int port) +{ + struct sockaddr_in prsin; + struct hostent *host_struct; + int conct; + + (void)uin; (void)port; + + prsin.sin_addr.s_addr = htonl(plink->icqlink->icq_ProxyIP); + if(prsin.sin_addr.s_addr == (unsigned long)-1) + { + prsin.sin_addr.s_addr = inet_addr(plink->icqlink->icq_ProxyHost); + if(prsin.sin_addr.s_addr == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */ + { + host_struct = gethostbyname(plink->icqlink->icq_ProxyHost); + if(host_struct == 0L) + { + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Can't find hostname: %s\n", + plink->icqlink->icq_ProxyHost); + return -1; + } + prsin.sin_addr = *((struct in_addr *)host_struct->h_addr); + } + } + prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/ + prsin.sin_port = htons(plink->icqlink->icq_ProxyPort); /* port */ +/* flags = fcntl(plink->socket, F_GETFL, 0); */ +/* fcntl(plink->socket, F_SETFL, flags & (~O_NONBLOCK)); */ + plink->mode |= TCP_LINK_SOCKS_CONNECTING; + conct = connect(plink->socket, (struct sockaddr *) &prsin, sizeof(prsin)); + if(conct == -1) /* did we connect ?*/ + { + if(errno != EINPROGRESS) + { + conct = errno; + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); + return conct; + } + return 1; + } + return 0; +} + +int icq_TCPLinkProxyRequestAuthorization(icq_TCPLink *plink) +{ + char buf[1024]; + + plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNECTING)); + buf[0] = 5; /* protocol version */ + buf[1] = 1; /* number of methods */ + if(!strlen(plink->icqlink->icq_ProxyName) || !strlen(plink->icqlink->icq_ProxyPass) || + !plink->icqlink->icq_ProxyAuth) + { + buf[2] = 0; /* no authorization required */ + plink->mode |= TCP_LINK_SOCKS_NOAUTHSTATUS; + } + else + { + buf[2] = 2; /* method username/password */ + plink->mode |= TCP_LINK_SOCKS_AUTHORIZATION; + } +#ifdef _WIN32 + if(send(plink->socket, buf, 3, 0) != 3) + return errno; +#else + if(write(plink->socket, buf, 3) != 3) + return errno; +#endif + return 0; +} + +int icq_TCPLinkProxyAuthorization(icq_TCPLink *plink) +{ + int res; + char buf[1024]; + + plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHORIZATION)) | TCP_LINK_SOCKS_AUTHSTATUS; +#ifdef _WIN32 + res = recv(plink->socket, buf, 2, 0); +#else + res = read(plink->socket, buf, 2); +#endif + if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/ + { + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); +#ifdef _WIN32 + closesocket(plink->socket); +#else + close(plink->socket); +#endif + return -1; + } + buf[0] = 1; /* version of subnegotiation */ + buf[1] = strlen(plink->icqlink->icq_ProxyName); + memcpy(&buf[2], plink->icqlink->icq_ProxyName, buf[1]); + buf[2+buf[1]] = strlen(plink->icqlink->icq_ProxyPass); + memcpy(&buf[3+buf[1]], plink->icqlink->icq_ProxyPass, buf[2+buf[1]]); +#ifdef _WIN32 + if(send(plink->socket, buf, buf[1]+buf[2+buf[1]]+3, 0) != buf[1] + buf[2+buf[1]]+3) + return errno; +#else + if(write(plink->socket, buf, buf[1]+buf[2+buf[1]]+3) != buf[1] + buf[2+buf[1]]+3) + return errno; +#endif + return 0; +} + +int icq_TCPLinkProxyAuthStatus(icq_TCPLink *plink) +{ + int res; + char buf[20]; + + plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT; +#ifdef _WIN32 + res = recv(plink->socket, buf, 2, 0); +#else + res = read(plink->socket, buf, 2); +#endif + if(res != 2 || buf[0] != 1 || buf[1] != 0) + { + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n"); +#ifdef _WIN32 + closesocket(plink->socket); +#else + close(plink->socket); +#endif + return -1; + } + return 0; +} + +int icq_TCPLinkProxyNoAuthStatus(icq_TCPLink *plink) +{ + int res; + char buf[20]; + + plink->mode = (plink->mode & (~TCP_LINK_SOCKS_NOAUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT; +#ifdef _WIN32 + res = recv(plink->socket, buf, 2, 0); +#else + res = read(plink->socket, buf, 2); +#endif + if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */ + { + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); +#ifdef _WIN32 + closesocket(plink->socket); +#else + close(plink->socket); +#endif + return -1; + } + return 0; +} + +int icq_TCPLinkProxyCrossConnect(icq_TCPLink *plink) +{ + char buf[20]; + + plink->mode = (plink->mode & ~(TCP_LINK_SOCKS_CROSSCONNECT)) | TCP_LINK_SOCKS_CONNSTATUS; + buf[0] = 5; /* protocol version */ + buf[1] = 1; /* command connect */ + buf[2] = 0; /* reserved */ + buf[3] = 1; /* address type IP v4 */ + memcpy(&buf[4], &plink->remote_address.sin_addr.s_addr, 4); + memcpy(&buf[8], &plink->remote_address.sin_port, 2); +#ifdef _WIN32 + if(send(plink->socket, buf, 10, 0) != 10) + return errno; +#else + if(write(plink->socket, buf, 10) != 10) + return errno; +#endif + return 0; +} + +int icq_TCPLinkProxyConnectStatus(icq_TCPLink *plink) +{ + int res; + char buf[1024]; + + plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNSTATUS)); +#ifdef _WIN32 + res = recv(plink->socket, buf, 10, 0); +#else + res = read(plink->socket, buf, 10); +#endif + if(res != 10 || buf[0] != 5 || buf[1] != 0) + { + switch(buf[1]) + { + case 1: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] General SOCKS server failure\n"); + res = EFAULT; + break; + case 2: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection not allowed by ruleset\n"); + res = EACCES; + break; + case 3: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Network unreachable\n"); + res = ENETUNREACH; + break; + case 4: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Host unreachable\n"); + res = ENETUNREACH; + break; + case 5: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n"); + res = ECONNREFUSED; + break; + case 6: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] TTL expired\n"); + res = ETIMEDOUT; + break; + case 7: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Command not supported\n"); + res = EOPNOTSUPP; + break; + case 8: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Address type not supported\n"); + res = EAFNOSUPPORT; + break; + default: + icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n"); + res = EFAULT; + break; + } +#ifdef _WIN32 + closesocket(plink->socket); +#else + close(plink->socket); +#endif + return res; + } + return 0; +} + +int icq_TCPLinkConnect(icq_TCPLink *plink, DWORD uin, int port) +{ + icq_ContactItem *pcontact=icq_ContactFind(plink->icqlink, uin); + icq_Packet *p; + int result; + +#ifndef _WIN32 + int flags; +#else + u_long iosflag; +#endif + + /* these return values never and nowhere checked */ + /* denis. */ + if(!pcontact) + return -2; + + if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -3; + +/* bzero(&(plink->remote_address), sizeof(plink->remote_address)); Win32 incompatible... */ + memset(&(plink->remote_address), 0, sizeof(plink->remote_address)); + plink->remote_address.sin_family = AF_INET; + + /* if our IP is the same as the remote user's ip, connect to real_ip + instead since we're both probably behind a firewall */ + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "local IP is %08X:%d, remote real IP is %08X:%d, remote IP is %08X:%d, port is %d\n", + plink->icqlink->icq_OurIP, + plink->icqlink->icq_OurPort, + pcontact->remote_real_ip, + pcontact->remote_port, + pcontact->remote_ip, + pcontact->remote_port, + port + ); + if (plink->icqlink->icq_OurIP == pcontact->remote_ip) + plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_real_ip); + else + plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_ip); + + if(plink->type==TCP_LINK_MESSAGE) + { + plink->remote_address.sin_port = htons(pcontact->remote_port); + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "initiating message connect to %d (%s:%d)\n", uin, + inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), + pcontact->remote_port); + } + else + { + plink->remote_address.sin_port = htons(port); + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "initiating file/chat connect to %d (%s:%d)\n", uin, + inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), + port); + } + + /* set the socket to non-blocking */ +#ifdef _WIN32 + iosflag = TRUE; + ioctlsocket(plink->socket, FIONBIO, &iosflag); +#else + flags=fcntl(plink->socket, F_GETFL, 0); + fcntl(plink->socket, F_SETFL, flags | O_NONBLOCK); +#endif + + if(!plink->icqlink->icq_UseProxy) + result=connect(plink->socket, (struct sockaddr *)&(plink->remote_address), + sizeof(plink->remote_address)); + else /* SOCKS proxy support */ + result=icq_TCPLinkProxyConnect(plink, uin, port); + /* FIXME: Here we should check for errors on connection */ + /* because of proxy support - it can't be checked */ + /* by getsockopt() later in _handle_ready_sockets() */ + /* denis. */ + + plink->mode|=TCP_LINK_MODE_CONNECTING; + + plink->remote_uin=uin; + + plink->connect_time=time(0L); + + /* Send the hello packet */ + p=icq_TCPCreateInitPacket(plink); + icq_TCPLinkSend(plink, p); + +#ifdef TCP_PACKET_TRACE + printf("hello packet queued for %lu\n", uin); +#endif /* TCP_PACKET_TRACE */ + + return 1; +} + +icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink) +{ +#ifdef _WIN32 + u_long iosflag; +#else + int flags; +#endif + int socket; + size_t remote_length; + icq_TCPLink *pnewlink=icq_TCPLinkNew( plink->icqlink ); + + if(pnewlink) + { + socket=accept(plink->socket, (struct sockaddr *)&(plink->remote_address), + &remote_length); + + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "accepting tcp connection from %s:%d\n", + inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), + ntohs(plink->remote_address.sin_port)); + + /* FIXME: make sure accept succeeded */ + + pnewlink->type=plink->type; + pnewlink->socket=socket; + + /* first packet sent on an icq tcp link is always the hello packet */ + pnewlink->mode|=TCP_LINK_MODE_HELLOWAIT; + } + + /* set the socket to non-blocking */ +#ifdef _WIN32 + iosflag = TRUE; + ioctlsocket(plink->socket, FIONBIO, &iosflag); +#else + flags=fcntl(pnewlink->socket, F_GETFL, 0); + fcntl(pnewlink->socket, F_SETFL, flags | O_NONBLOCK); +#endif + + return pnewlink; +} + +int icq_TCPLinkListen(icq_TCPLink *plink) +{ + unsigned int t; + + /* listening links have 0 uin */ + plink->remote_uin=0; + + /* create tcp listen socket */ + if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + /* must use memset, no bzero for Win32! */ + memset(&plink->socket_address, 0, sizeof(struct sockaddr_in)); + plink->socket_address.sin_family=AF_INET; + plink->socket_address.sin_addr.s_addr=htonl(INADDR_ANY); + plink->socket_address.sin_port=0; + + if(bind(plink->socket, (struct sockaddr *)&plink->socket_address, sizeof(struct sockaddr_in)) < 0) + return -2; + + if(listen(plink->socket, 5) < 0) + return -3; + + t=sizeof(struct sockaddr_in); + if(getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &t) < 0) + return -4; + + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "created tcp listening socket %d, local address=%s:%d\n", + plink->socket, + inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))), + ntohs(plink->socket_address.sin_port)); + + plink->mode|=TCP_LINK_MODE_LISTEN; + + return 0; +} + +/* Doing Cyrillic translations for Chat dialog sessions */ +void icq_ChatRusConv_n(const char to[4], char *t_in, int t_len) +{ + int i, j; + + for(i = j = 0; i < t_len; ++i) + { + if((((unsigned char)t_in[i]) < ' ') && (t_in[i] != '\r')) + { + if(i - 1 > j) + icq_RusConv_n(to, &t_in[j], i - j - 1); + switch(t_in[i]) + { + case '\x07': /* Bell */ + case '\x08': /* BackSpace */ + case '\x03': /* Chat is active */ + case '\x04': /* Chat is not active */ + break; + case '\x00': /* Foregroung color (RR GG BB ?? ) */ + case '\x01': /* Background color (RR GG BB ?? ) */ + case '\x11': /* Font style change (Bold - 1, Italic - 2, Underline - 4) */ + case '\x12': /* Font size change */ + i += 4; + break; + case '\x10': /* Font family and encoding change */ + i += t_in[i+1] + 2 + 2; + icq_RusConv_n(to, &t_in[i+3], t_in[i+1]); + break; + } + j = i + 1; + } + } + if(i > t_len) + i = t_len; + if(j > t_len) + j = t_len; + if(i > j) + icq_RusConv_n(to, &t_in[j], i - j); +} + +int icq_TCPLinkOnDataReceived(icq_TCPLink *plink) +{ + int process_count=0, recv_result=0; + char *buffer=plink->buffer; + + do { /* while recv_result > 0 */ + + int done=0; + + /* append received data onto end of buffer */ + if((recv_result=recv(plink->socket, buffer+plink->buffer_count, + icq_TCPLinkBufferSize-plink->buffer_count, 0)) < 1) + { + /* either there was an error or the remote side has closed + * the connection - fall out of the loop */ + continue; + }; + + plink->buffer_count+=recv_result; + +#ifdef TCP_BUFFER_TRACE + printf("received %d bytes from link %x, new buffer count %d\n", + recv_result, plink, plink->buffer_count); + + hex_dump(plink->buffer, plink->buffer_count); +#endif /*TCP_BUFFER_TRACE*/ + + process_count+=recv_result; + + /* don't do any packet processing if we're in raw mode */ + if(plink->mode & TCP_LINK_MODE_RAW) { + /* notify the app with the new data */ + if(plink->type == TCP_LINK_CHAT) + icq_ChatRusConv_n("wk", plink->buffer, plink->buffer_count); + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, + plink->buffer_count, plink->buffer); + plink->buffer_count=0; + continue; + } + + /* remove packets from the buffer until the buffer is empty + * or the remaining bytes do not equal a full packet */ + while((unsigned)plink->buffer_count>sizeof(WORD) && !done) + { + WORD packet_size=(*((WORD *)buffer)); + + /* warn if the buffer is too small to hold the whole packet */ + if(packet_size>icq_TCPLinkBufferSize-sizeof(WORD)) + { + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "tcplink buffer " + "overflow, packet size = %d, buffer size = %d, closing link\n", + packet_size, icq_TCPLinkBufferSize); + icq_TCPLinkClose(plink); + return 0; + } + + if(packet_size+sizeof(WORD) <= (unsigned)plink->buffer_count) + { + /* copy the packet into memory */ + icq_Packet *p=icq_PacketNew(); + icq_PacketAppend(p, buffer+sizeof(WORD), packet_size); + + /* remove it from the buffer */ + memcpy(buffer, buffer+packet_size+sizeof(WORD), + plink->buffer_count-packet_size-sizeof(WORD)); + + plink->buffer_count-=(packet_size+sizeof(WORD)); + + icq_TCPLinkOnPacketReceived(plink, p); + } + else + { + /* not enough bytes in buffer to form the complete packet. + * we're done for now */ + done=1; + } + } /* while packets remain in buffer */ + + } while (recv_result > 0); + + if (recv_result < 0 && errno!=EWOULDBLOCK) { + + /* receive error - log it */ + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "recv failed from %d (%d-%s)," + " closing link\n", plink->remote_uin, errno, strerror(errno)); + + } + + return process_count; +} + +void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p) +{ + +#ifdef TCP_RAW_TRACE + printf("packet received! { length=%d }\n", p->length); + icq_PacketDump(p); +#endif + + /* Stick packet on ready packet linked list */ + list_enqueue(plink->received_queue, p); +} + +void icq_TCPLinkOnConnect(icq_TCPLink *plink) +{ +#ifdef _WIN32 + int len; +#else + size_t len; +#endif + int error; + + /* check getsockopt */ + len=sizeof(error); + +#ifdef _WIN32 + getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, (char *)&error, &len); +#else + getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, &error, &len); +#endif + if(!error && (plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | + TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | + TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS))) + { + if(plink->mode & TCP_LINK_SOCKS_CONNECTING) + error = icq_TCPLinkProxyRequestAuthorization(plink); + else if(plink->mode & TCP_LINK_SOCKS_AUTHORIZATION) + error = icq_TCPLinkProxyAuthorization(plink); + else if(plink->mode & TCP_LINK_SOCKS_AUTHSTATUS) + error = icq_TCPLinkProxyAuthStatus(plink); + else if(plink->mode & TCP_LINK_SOCKS_NOAUTHSTATUS) + error = icq_TCPLinkProxyNoAuthStatus(plink); + else if(plink->mode & TCP_LINK_SOCKS_CROSSCONNECT) + error = icq_TCPLinkProxyCrossConnect(plink); + else if(plink->mode & TCP_LINK_SOCKS_CONNSTATUS) + error = icq_TCPLinkProxyConnectStatus(plink); + else + error = EINVAL; + } + + if(error) + { + /* connection failed- close the link, which takes care + * of notifying the app about packets that didn't make it */ + icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "connect failed to %d (%d-%s)," + " closing link\n", plink->remote_uin, error, strerror(error)); + + icq_TCPLinkClose(plink); + return; + } + + if(plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS)) + return; + + len=sizeof(plink->socket_address); + getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &len); + + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "connected to uin %d, socket=%d local address=%s:%d remote address=%s:%d\n", + plink->remote_uin, plink->socket, + inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))), + ntohs(plink->socket_address.sin_port), + inet_ntoa(*((struct in_addr *)(&plink->remote_address.sin_addr))), + ntohs(plink->remote_address.sin_port)); + + plink->mode&= ~TCP_LINK_MODE_CONNECTING; + + /* socket is now connected, notify each request that connection + * has been established and send pending data */ + while(plink->send_queue->count>0) + { + icq_Packet *p=list_dequeue(plink->send_queue); + if(p->id) + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTED, 0, 0); + icq_TCPLinkSend(plink, p); + } + + /* yeah this probably shouldn't be here. oh well :) */ + if(plink->type==TCP_LINK_CHAT) + { + icq_ChatSessionSetStatus((icq_ChatSession *)plink->session, + CHAT_STATUS_CONNECTED); + icq_ChatSessionSetStatus((icq_ChatSession *)plink->session, + CHAT_STATUS_WAIT_ALLINFO); + } + + if(plink->type==TCP_LINK_FILE) + { + icq_FileSessionSetStatus((icq_FileSession *)plink->session, + FILE_STATUS_CONNECTED); + } + +} + +unsigned long icq_TCPLinkSendSeq(icq_TCPLink *plink, icq_Packet *p, + unsigned long sequence) +{ + /* append the next sequence number on the packet */ + if (!sequence) + sequence=plink->icqlink->icq_TCPSequence--; + p->id=sequence; + icq_PacketEnd(p); + icq_PacketAppend32(p, sequence); + + /* if the link is currently connecting, queue the packets for + * later, else send immediately */ + if(plink->mode & TCP_LINK_MODE_CONNECTING) { + list_insert(plink->send_queue, 0, p); + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0); + } else { + icq_PacketSend(p, plink->socket); + if(p->id) + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0); + icq_PacketDelete(p); + } + return sequence; +} + +void icq_TCPLinkSend(icq_TCPLink *plink, icq_Packet *p) +{ + /* if the link is currently connecting, queue the packets for + * later, else send immediately */ + if(plink->mode & TCP_LINK_MODE_CONNECTING) { + list_insert(plink->send_queue, 0, p); + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0); + } else { + icq_PacketSend(p, plink->socket); + if(p->id) + if(plink->icqlink->icq_RequestNotify) + (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0); + icq_PacketDelete(p); + } +} + +void icq_TCPLinkProcessReceived(icq_TCPLink *plink) +{ + list *plist=plink->received_queue; + while(plist->count>0) + + { + icq_Packet *p=list_dequeue(plist); + + if(plink->mode & TCP_LINK_MODE_HELLOWAIT) + { + icq_TCPProcessHello(p, plink); + } + else + { + + switch (plink->type) { + + case TCP_LINK_MESSAGE: + icq_TCPProcessPacket(p, plink); + break; + + case TCP_LINK_CHAT: + icq_TCPProcessChatPacket(p, plink); + break; + + case TCP_LINK_FILE: + icq_TCPProcessFilePacket(p, plink); + break; + + } + } + + icq_PacketDelete(p); + } + +} + +int _icq_FindTCPLink(void *p, va_list data) +{ + icq_TCPLink *plink=(icq_TCPLink *)p; + unsigned long uin=va_arg(data, unsigned long); + int type=va_arg(data, int); + + return ( (plink->remote_uin == uin ) && (plink->type == type) ); +} + +icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type) +{ + return list_traverse(link->icq_TCPLinks, _icq_FindTCPLink, uin, type); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/tcplink.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _TCP_LINK_H_ +#define _TCP_LINK_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef _WIN32 +#include <winsock.h> +#else +#include <netinet/in.h> +#endif + +#include <time.h> + +#include "icq.h" +#include "icqpacket.h" +#include "list.h" + +/* link mode bitfield values */ +#define TCP_LINK_MODE_RAW 1 +#define TCP_LINK_MODE_HELLOWAIT 2 +#define TCP_LINK_MODE_LISTEN 4 +#define TCP_LINK_MODE_CONNECTING 8 +#define TCP_LINK_SOCKS_CONNECTING 16 +#define TCP_LINK_SOCKS_AUTHORIZATION 32 +#define TCP_LINK_SOCKS_AUTHSTATUS 64 +#define TCP_LINK_SOCKS_NOAUTHSTATUS 128 +#define TCP_LINK_SOCKS_CROSSCONNECT 256 +#define TCP_LINK_SOCKS_CONNSTATUS 512 + +/* link types */ +#define TCP_LINK_MESSAGE 1 +#define TCP_LINK_CHAT 2 +#define TCP_LINK_FILE 3 + +#define icq_TCPLinkBufferSize 4096 +#define TCP_LINK_CONNECT_TIMEOUT 30 + +typedef struct icq_TCPLink_s +{ + /* icq_TCPLink ICQLINK, type, mode, and session */ + ICQLINK *icqlink; + int type; + int mode; + int proxy_status; + void *session; + + /* socket parameters */ + int socket; + struct sockaddr_in socket_address; + struct sockaddr_in remote_address; + + /* data buffer for receive calls */ + char buffer[icq_TCPLinkBufferSize]; + int buffer_count; + + /* packet queues */ + list *received_queue; + list *send_queue; + + /* icq specific data, initialized by hello packet */ + unsigned long id; + unsigned long remote_version; + unsigned long remote_uin; + char flags; + + /* connect timer */ + time_t connect_time; + +} icq_TCPLink; + +icq_TCPLink *icq_TCPLinkNew(ICQLINK *link); +void icq_TCPLinkDelete(void *p); +void icq_TCPLinkClose(icq_TCPLink *p); +void icq_TCPLinkNodeDelete(list_node *p); + +int icq_TCPLinkConnect(icq_TCPLink *plink, DWORD uin, int port); +icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink); +int icq_TCPLinkListen(icq_TCPLink *plink); + +int icq_TCPLinkOnDataReceived(icq_TCPLink *plink); +void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p); +void icq_TCPLinkOnConnect(icq_TCPLink *plink); + +unsigned long icq_TCPLinkSendSeq(icq_TCPLink *plink, icq_Packet *p, + unsigned long sequence); +void icq_TCPLinkSend(icq_TCPLink *plink, icq_Packet *p); + +void icq_TCPLinkProcessReceived(icq_TCPLink *plink); + +icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type); + +void icq_ChatRusConv_n(const char to[4], char *t_in, int t_len); + +#endif /* _TCP_LINK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/udp.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,785 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: udp.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.23 2000/07/09 22:19:35 bills +added new *Close functions, use *Close functions instead of *Delete +where correct, and misc cleanup + +Revision 1.22 2000/07/09 18:25:44 denis +icq_UpdateNewUserInfo() now returns seq1 instead of seq2 since it +isn't META function. + +Revision 1.21 2000/06/25 16:43:19 denis +icq_SendMetaInfoReq() was added. +All icq_*Meta*() functions now returns sequence number 2 because their +replies from the server are synced with it. + +Revision 1.20 2000/06/15 01:50:39 bills +removed *Seq functions + +Revision 1.19 2000/05/10 19:06:59 denis +UDP outgoing packet queue was implemented. + +Revision 1.18 2000/05/03 18:34:43 denis +icq_UpdateNewUserInfo() was added. +All icq_UpdateMetaInfo*() now return their sequence number. + +Revision 1.17 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.16 2000/04/06 19:03:07 denis +return sequence number + +Revision 1.15 2000/04/06 16:36:18 denis +So called "Online List problem" bug with Long Contact List was fixed. +icq_*Send*Seq() functions with specified sequence number were added. + +Revision 1.14 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.13 1999/12/27 11:12:35 denis +icq_UpdateMetaInfoSecurity() added for setting "My authorization is +required", "Web Aware" and "IP Publishing". + +Revision 1.12 1999/10/14 11:43:28 denis +icq_UpdateMetaInfo* functions added. + +Revision 1.11 1999/10/07 18:36:27 denis +proxy.h file removed. + +Revision 1.10 1999/10/04 13:36:17 denis +Cleanups. + +Revision 1.9 1999/09/29 20:15:30 bills +tcp port wasn't being sent properly in login packet + +Revision 1.8 1999/09/29 17:13:45 denis +Webaware functions enabled without success even with UDP v5 - need more +investigations. + +Revision 1.7 1999/07/18 20:22:16 bills +changed to use new byte-order functions & contact list functions + +Revision 1.6 1999/07/16 15:46:00 denis +Cleaned up. + +Revision 1.5 1999/07/16 12:40:53 denis +ICQ UDP v5 implemented. +Encription for ICQ UDP v5 implemented. +icq_Packet* unified interface for UDP packets implemented. +Multipacket support of ICQ UDP v5 support added. + +Revision 1.4 1999/07/12 15:13:43 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.3 1999/04/29 09:40:52 denis +Unsuccessful attempt to implement web presence (webaware) feature + +Revision 1.2 1999/04/14 15:04:13 denis +Cleanups for "strict" compiling (-ansi -pedantic) +Switched from icq_Log callback to icq_Fmt function. + +Revision 1.1 1999/03/24 11:37:38 denis +Underscored files with TCP stuff renamed. +TCP stuff cleaned up +Function names changed to corresponding names. +icqlib.c splitted to many small files by subject. +C++ comments changed to ANSI C comments. + +*/ + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#ifdef _WIN32 +#include <winsock.h> +#endif + +#include <stdlib.h> + +#include "icqtypes.h" +#include "icqlib.h" +#include "udp.h" +#include "queue.h" + +#include "stdpackets.h" +#include "icqbyteorder.h" + +static const BYTE icq_UDPTable[] = { + 0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D, + 0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39, + 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42, + 0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48, + 0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54, + 0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36, + 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A, + 0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35, + 0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B, + 0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, + 0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C, + 0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E, + 0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58, + 0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41, + 0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, + 0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00, +}; + +void icq_UDPCheckCode(icq_Packet *p) +{ + DWORD num1, num2; + DWORD r1,r2; + + num1 = p->data[8]; + num1 <<= 8; + num1 += p->data[4]; + num1 <<= 8; + num1 += p->data[2]; + num1 <<= 8; + num1 += p->data[6]; + + r1 = 0x18 + (rand() % (p->length - 0x18)); + r2 = rand() & 0xff; + + num2 = r1; + num2 <<= 8; + num2 += p->data[r1]; + num2 <<= 8; + num2 += r2; + num2 <<= 8; + num2 += icq_UDPTable[r2]; + num2 ^= 0xFF00FF; + + icq_PacketGoto(p, 0x14); + icq_PacketAppend32(p, num1 ^ num2); +} + +DWORD icq_UDPScramble(DWORD cc) +{ + DWORD a[5]; + + a[0] = cc & 0x0000001F; + a[1] = cc & 0x03E003E0; + a[2] = cc & 0xF8000400; + a[3] = cc & 0x0000F800; + a[4] = cc & 0x041F0000; + + a[0] <<= 0x0C; + a[1] <<= 0x01; + a[2] >>= 0x0A; + a[3] <<= 0x10; + a[4] >>= 0x0F; + + return a[0] + a[1] + a[2] + a[3] + a[4]; +} + +void icq_UDPEncode(icq_Packet *p) +{ + DWORD checkcode; + DWORD code1, code2, code3; + DWORD pos; + DWORD data; + + icq_UDPCheckCode(p); + icq_PacketGoto(p, 20); + checkcode = icq_PacketRead32(p); + code1 = p->length * 0x68656c6cL; + code2 = code1 + checkcode; + pos = 0x0A; + + for(; pos < p->length; pos+=4) + { + code3 = code2 + icq_UDPTable[pos & 0xFF]; + data = icqtohl(*(DWORD *)((p->data)+pos)); + data ^= code3; + *(DWORD*)((p->data)+pos)=htoicql(data); + } + checkcode = icq_UDPScramble(checkcode); + *(DWORD *)((p->data)+0x14)=htoicql(checkcode); +} + +/********************************************************* +icq_UDPSockWrite and icq_UDPSockRead are for _UDP_ packets +proxy support for TCP sockets is different! +*********************************************************/ +int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet *p) +{ + char tmpbuf[ICQ_PACKET_DATA_SIZE]; + + if(link->icq_UDPSok <= 3) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad socket!\n"); + return -1; + } + + icq_UDPEncode(p); + if(!link->icq_UseProxy) + { +#ifdef _WIN32 + return send(link->icq_UDPSok, p->data, p->length, 0); +#else + return write(link->icq_UDPSok, p->data, p->length); +#endif + } + else + { + tmpbuf[0] = 0; /* reserved */ + tmpbuf[1] = 0; /* reserved */ + tmpbuf[2] = 0; /* standalone packet */ + tmpbuf[3] = 1; /* address type IP v4 */ + *(unsigned long*)&tmpbuf[4] = htonl(link->icq_ProxyDestIP); + *(unsigned short*)&tmpbuf[8] = htons(link->icq_ProxyDestPort); + memcpy(&tmpbuf[10], p->data, p->length); +#ifdef _WIN32 + return send(link->icq_UDPSok, tmpbuf, p->length+10, 0)-10; +#else + return write(link->icq_UDPSok, tmpbuf, p->length+10)-10; +#endif + } +} + +int icq_UDPSockWrite(ICQLINK *link, icq_Packet *p) +{ + icq_Packet *qp; + WORD cmd = icq_PacketReadUDPOutCmd(p); + if(cmd != UDP_CMD_ACK && cmd != UDP_CMD_SEND_TEXT_CODE) + { + qp = (icq_Packet*)malloc(sizeof(icq_Packet)); + memcpy(qp, p, sizeof(icq_Packet)); + icq_UDPQueuePut(link, qp, 1); + if(link->icq_SetTimeout) + link->icq_SetTimeout(link, icq_UDPQueueInterval(link)); + } + return icq_UDPSockWriteDirect(link, p); +} + +int icq_UDPSockRead(ICQLINK *link, icq_Packet *p) +{ + int res; + char tmpbuf[ICQ_PACKET_DATA_SIZE]; + + if(!link->icq_UseProxy) + { +#ifdef _WIN32 + res = recv(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE, 0); +#else + res = read(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE); +#endif + p->length = res; + return res; + } + else + { +#ifdef _WIN32 + res = recv(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE, 0); +#else + res = read(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE); +#endif + if(res<0) + return res; + memcpy(p->data, &tmpbuf[10], res-10); + p->length = res-10; + return res-10; + } +} + +void icq_HandleTimeout(ICQLINK *link) +{ + icq_UDPQueueItem *ptr = 0; + icq_Packet *sp = 0, *pack = 0; + int attempt; + while(icq_UDPQueueInterval(link) == 0) + { + ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue); + attempt = ptr->attempts + 1; + if(attempt > 6) + { + icq_Disconnect(link); + if(link->icq_Disconnected) + link->icq_Disconnected(link); + return; + } + pack = icq_UDPQueueGet(link); + sp = (icq_Packet*)malloc(sizeof(icq_Packet)); + memcpy(sp, pack, sizeof(icq_Packet)); + icq_UDPQueuePut(link, pack, attempt); + if(link->icq_SetTimeout) + link->icq_SetTimeout(link, icq_UDPQueueInterval(link)); + icq_UDPSockWriteDirect(link, sp); + icq_PacketDelete(sp); + } +} + +/**************************************** +This must be called every 2 min. +so the server knows we're still alive. +JAVA client sends two different commands +so we do also :) +*****************************************/ +WORD icq_KeepAlive(ICQLINK *link) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_KEEP_ALIVE, link->icq_UDPSeqNum1++); + icq_PacketAppend32(p, rand()); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + +/* icq_Packet *p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE); + icq_UDPSockWrite(icq_UDPSok, p); + icq_PacketDelete(p);*/ +/* p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE2); + icq_UDPSockWrite(icq_Sok, p); + icq_PacketDelete(p);*/ + + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send Keep Alive packet to the server\n"); + + return link->icq_UDPSeqNum1-1; +} + +/********************************** +This must be called to remove +messages from the server +***********************************/ +void icq_SendGotMessages(ICQLINK *link) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ACK_MESSAGES); + icq_PacketAppend32(p, rand()); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/************************************* +this sends over the contact list +*************************************/ +void icq_SendContactList(ICQLINK *link) /* V5 */ +{ + char num_used; + icq_ContactItem *ptr = icq_ContactGetFirst(link); + + while(ptr) + { + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_CONT_LIST); + + num_used = 0; + icq_PacketAdvance(p,1); + while(ptr && num_used<64) + { + icq_PacketAppend32(p, ptr->uin); + num_used++; + ptr = icq_ContactGetNext(ptr); + } + icq_PacketGotoUDPOutData(p, 0); + icq_PacketAppend8(p, num_used); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + } +} + +void icq_SendNewUser(ICQLINK *link, unsigned long uin) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ADD_TO_LIST); + icq_PacketAppend32(p, uin); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/************************************* +this sends over the visible list +that allows certain users to see you +if you're invisible. +*************************************/ +void icq_SendVisibleList(ICQLINK *link) /* V5 */ +{ + char num_used; + icq_ContactItem *ptr = icq_ContactGetFirst(link); + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_VIS_LIST); + + num_used = 0; + icq_PacketAdvance(p,1); + while(ptr) + { + if(ptr->vis_list) + { + icq_PacketAppend32(p, ptr->uin); + num_used++; + } + ptr = icq_ContactGetNext(ptr); + } + if(num_used != 0) + { + icq_PacketGotoUDPOutData(p, 0); + icq_PacketAppend8(p, num_used); + icq_UDPSockWrite(link, p); + } + icq_PacketDelete(p); +} + +void icq_SendInvisibleList(ICQLINK *link) /* V5 */ +{ + char num_used; + icq_ContactItem *ptr = icq_ContactGetFirst(link); + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INVIS_LIST); + + num_used = 0; + icq_PacketAdvance(p,1); + while(ptr) + { + if(ptr->vis_list) + { + icq_PacketAppend32(p, ptr->uin); + num_used++; + } + ptr = icq_ContactGetNext(ptr); + } + if(num_used != 0) + { + icq_PacketGotoUDPOutData(p, 0); + icq_PacketAppend8(p, num_used); + icq_UDPSockWrite(link, p); + } + icq_PacketDelete(p); +} + +/************************************** +This sends the second login command +this is necessary to finish logging in. +***************************************/ +void icq_SendLogin1(ICQLINK *link) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN_1); + icq_PacketAppend32(p, rand()); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/************************************ +This procedure logins into the server with icq_Uin and pass +on the socket icq_Sok and gives our ip and port. +It does NOT wait for any kind of a response. +*************************************/ +void icq_Login(ICQLINK *link, DWORD status) /* V5 */ +{ + icq_Packet *p; + + memset(link->icq_UDPServMess, FALSE, sizeof(link->icq_UDPServMess)); + link->icq_UDPSession = rand() & 0x3FFFFFFF; + link->icq_UDPSeqNum1 = rand() & 0x7FFF; + link->icq_UDPSeqNum2 = 1; + + p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN); + icq_PacketAppend32(p, time(0L)); + icq_PacketAppend32n(p, link->icq_TCPSrvPort); + /*icq_PacketAppend16(p, 0); + icq_PacketAppend16n(p, htons(link->icq_OurPort));*/ + icq_PacketAppendString(p, link->icq_Password); + icq_PacketAppend32(p, LOGIN_X1_DEF); + icq_PacketAppend32n(p, htonl(link->icq_OurIP)); + if(link->icq_UseProxy) + icq_PacketAppend8(p, LOGIN_SNDONLY_TCP); + else + icq_PacketAppend8(p, LOGIN_SNDRCV_TCP); + icq_PacketAppend32(p, status); + icq_PacketAppend32(p, LOGIN_X3_DEF); + icq_PacketAppend32(p, LOGIN_X4_DEF); + icq_PacketAppend32(p, LOGIN_X5_DEF); + + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/********************** +Logs off ICQ +***********************/ +void icq_Logout(ICQLINK *link) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_SEND_TEXT_CODE, link->icq_UDPSeqNum1++); + icq_PacketAppendString(p, "B_USER_DISCONNECTED"); + icq_PacketAppend8(p, 5); + icq_PacketAppend8(p, 0); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/******************************* +This routine sends the aknowlegement cmd to the +server it appears that this must be done after +everything the server sends us +*******************************/ +void icq_UDPAck(ICQLINK *link, int seq) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_ACK, seq); + icq_PacketAppend32(p, rand()); + + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acking\n"); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/*************************************************** +Sends a message thru the server to uin. Text is the +message to send. +***************************************************/ +WORD icq_UDPSendMessage(ICQLINK *link, DWORD uin, const char *text) /* V5 */ +{ + char buf[512]; /* message may be only 450 bytes long */ + icq_Packet *p; + + strncpy(buf, text, 512); + icq_RusConv("kw", buf); + + p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); + icq_PacketAppend32(p, uin); + icq_PacketAppend16(p, TYPE_MSG); + icq_PacketAppendString(p, buf); + + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr) /* V5 */ +{ + char buf1[512], buf2[512]; + icq_Packet *p; + + strncpy(buf1, descr, 512); + icq_RusConv("kw", buf1); + strncpy(buf2, url, 512); + + p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); + icq_PacketAppend32(p, uin); + icq_PacketAppend16(p, TYPE_URL); + icq_PacketAppend16(p, strlen(buf1)+strlen(buf2)+2); /* length + the NULL + 0xFE delimiter */ + icq_PacketAppendStringFE(p, buf1); + icq_PacketAppendString0(p, buf2); + + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +/************************************************** +Sends a authorization to the server so the Mirabilis +client can add the user. +***************************************************/ +WORD icq_SendAuthMsg(ICQLINK *link, DWORD uin) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV); + icq_PacketAppend32(p, uin); + icq_PacketAppend32(p, TYPE_AUTH); + icq_PacketAppend16(p, 0); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + + return link->icq_UDPSeqNum1-1; +} + +/************************************************** +Changes the users status on the server +***************************************************/ +void icq_ChangeStatus(ICQLINK *link, DWORD status) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_STATUS_CHANGE); + icq_PacketAppend32(p, status); + link->icq_Status = status; + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/******************************************************** +Sends a request to the server for info on a specific user +*********************************************************/ +WORD icq_SendInfoReq(ICQLINK *link, DWORD uin) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INFO_REQ); + icq_PacketAppend32(p, uin); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +/******************************************************** +Sends a request to the server for info on a specific user +*********************************************************/ +WORD icq_SendExtInfoReq(ICQLINK *link, DWORD uin) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_EXT_INFO_REQ); + icq_PacketAppend32(p, uin); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +/************************************************************** +Initializes a server search for the information specified +***************************************************************/ +void icq_SendSearchReq(ICQLINK *link, const char *email, const char *nick, const char *first, + const char *last) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_USER); + icq_PacketAppendString(p, nick); + icq_PacketAppendString(p, first); + icq_PacketAppendString(p, last); + icq_PacketAppendString(p, email); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/************************************************************** +Initializes a server search for the information specified +***************************************************************/ +void icq_SendSearchUINReq(ICQLINK *link, DWORD uin) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_UIN); + icq_PacketAppend32(p, uin); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); +} + +/************************************************** +Registers a new uin in the ICQ network +***************************************************/ +void icq_RegNewUser(ICQLINK *link, const char *pass) /* V5 */ +{ + char pass8[9]; + icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_REG_NEW_USER, link->icq_UDPSeqNum1++); + strncpy(pass8, pass, 8); + icq_PacketAppendString(p, pass8); + icq_PacketAppend32(p, 0xA0); + icq_PacketAppend32(p, 0x2461); + icq_PacketAppend32(p, 0xA00000); + icq_PacketAppend32(p, 0x00); + icq_PacketGoto(p, 6); + icq_PacketAppend32(p, 0); + icq_PacketAppend32(p, rand()); + icq_UDPSockWrite(link, p); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send RegNewUser packet to the server\n"); + icq_PacketDelete(p); +} + +WORD icq_UpdateUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last, + const char *email) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_INFO); + icq_PacketAppendString(p, nick); + icq_PacketAppendString(p, first); + icq_PacketAppendString(p, last); + icq_PacketAppendString(p, email); +/* auth (byte)? */ + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +WORD icq_UpdateAuthInfo(ICQLINK *link, DWORD auth) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_AUTH); + icq_PacketAppend32(p, auth); /* NOT auth? */ + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +WORD icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick, const char *first, const char *last, + const char *email, const char *email2, const char *email3, + const char *city, const char *state, const char *phone, const char *fax, + const char *street, const char *cellular, unsigned long zip, + unsigned short cnt_code, unsigned char cnt_stat, unsigned char emailhide) +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); + icq_PacketAppend16(p, META_CMD_SET_INFO); + icq_PacketAppendString(p, nick); + icq_PacketAppendString(p, first); + icq_PacketAppendString(p, last); + icq_PacketAppendString(p, email); + icq_PacketAppendString(p, email2); + icq_PacketAppendString(p, email3); + icq_PacketAppendString(p, city); + icq_PacketAppendString(p, state); + icq_PacketAppendString(p, phone); + icq_PacketAppendString(p, fax); + icq_PacketAppendString(p, street); + icq_PacketAppendString(p, cellular); + icq_PacketAppend32(p, zip); + icq_PacketAppend16(p, cnt_code); + icq_PacketAppend8(p, cnt_stat); + icq_PacketAppend8(p, emailhide); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum2-1; +} + +WORD icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age, const char *homepage, + unsigned char year, unsigned char month, unsigned char day, + unsigned char lang1, unsigned char lang2, unsigned char lang3) +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); + icq_PacketAppend16(p, META_CMD_SET_HOMEPAGE); + icq_PacketAppend8(p, age); + icq_PacketAppend16(p, 0x0200); + icq_PacketAppendString(p, homepage); + icq_PacketAppend8(p, year); + icq_PacketAppend8(p, month); + icq_PacketAppend8(p, day); + icq_PacketAppend8(p, 0xFF /* lang1 */); + icq_PacketAppend8(p, 0xFF /* lang2 */); + icq_PacketAppend8(p, 0xFF /* lang3 */); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum2-1; +} + +WORD icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about) +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); + icq_PacketAppend16(p, META_CMD_SET_ABOUT); + icq_PacketAppendString(p, about); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum2-1; +} + +WORD icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth, unsigned char webpresence, + unsigned char pubip) +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); + icq_PacketAppend16(p, META_CMD_SET_SECURE); + icq_PacketAppend8(p, !reqauth); + icq_PacketAppend8(p, webpresence); + icq_PacketAppend8(p, pubip); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum2-1; +} + +WORD icq_UpdateNewUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last, + const char *email) /* V5 */ +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_NEW_USER_INFO); + icq_PacketAppendString(p, nick); + icq_PacketAppendString(p, first); + icq_PacketAppendString(p, last); + icq_PacketAppendString(p, email); + icq_PacketAppend8(p, 1); + icq_PacketAppend8(p, 1); + icq_PacketAppend8(p, 1); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum1-1; +} + +WORD icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin) +{ + icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER); + icq_PacketAppend16(p, META_CMD_REQ_INFO); + icq_PacketAppend32(p, uin); + icq_UDPSockWrite(link, p); + icq_PacketDelete(p); + return link->icq_UDPSeqNum2-1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/udp.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _UDP_H_ +#define _UDP_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "icq.h" +#include "util.h" +#include "icqpacket.h" + +#define UDP_CMD_ACK 0x000A +#define UDP_CMD_SEND_THRU_SRV 0x010E +#define UDP_CMD_LOGIN 0x03E8 +#define UDP_CMD_CONT_LIST 0x0406 +#define UDP_CMD_SEARCH_UIN 0x041A +#define UDP_CMD_SEARCH_USER 0x0424 +#define UDP_CMD_KEEP_ALIVE 0x042E +#define UDP_CMD_KEEP_ALIVE2 0x051E +#define UDP_CMD_SEND_TEXT_CODE 0x0438 +#define UDP_CMD_LOGIN_1 0x044C +#define UDP_CMD_INFO_REQ 0x0460 +#define UDP_CMD_EXT_INFO_REQ 0x046A +#define UDP_CMD_CHANGE_PW 0x049C +#define UDP_CMD_STATUS_CHANGE 0x04D8 +#define UDP_CMD_LOGIN_2 0x0528 +#define UDP_CMD_UPDATE_INFO 0x050A +#define UDP_CMD_UPDATE_AUTH 0x0514 +#define UDP_CMD_UPDATE_EXT_INFO 0x04B0 +#define UDP_CMD_ADD_TO_LIST 0x053C +#define UDP_CMD_REQ_ADD_LIST 0x0456 +#define UDP_CMD_QUERY_SERVERS 0x04BA +#define UDP_CMD_QUERY_ADDONS 0x04C4 +#define UDP_CMD_NEW_USER_1 0x04EC +#define UDP_CMD_NEW_USER_INFO 0x04A6 +#define UDP_CMD_ACK_MESSAGES 0x0442 +#define UDP_CMD_MSG_TO_NEW_USER 0x0456 +#define UDP_CMD_REG_NEW_USER 0x03FC +#define UDP_CMD_VIS_LIST 0x06AE +#define UDP_CMD_INVIS_LIST 0x06A4 +#define UDP_CMD_META_USER 0x064A +#define UDP_CMD_RAND_SEARCH 0x056E +#define UDP_CMD_RAND_SET 0x0564 +#define UDP_CMD_REVERSE_TCP_CONN 0x015E + +#define UDP_SRV_ACK 0x000A +#define UDP_SRV_LOGIN_REPLY 0x005A +#define UDP_SRV_USER_ONLINE 0x006E +#define UDP_SRV_USER_OFFLINE 0x0078 +#define UDP_SRV_USER_FOUND 0x008C +#define UDP_SRV_OFFLINE_MESSAGE 0x00DC +#define UDP_SRV_END_OF_SEARCH 0x00A0 +#define UDP_SRV_INFO_REPLY 0x0118 +#define UDP_SRV_EXT_INFO_REPLY 0x0122 +#define UDP_SRV_STATUS_UPDATE 0x01A4 +#define UDP_SRV_X1 0x021C +#define UDP_SRV_X2 0x00E6 +#define UDP_SRV_UPDATE 0x01E0 +#define UDP_SRV_UPDATE_EXT 0x00C8 +#define UDP_SRV_NEW_UIN 0x0046 +#define UDP_SRV_NEW_USER 0x00B4 +#define UDP_SRV_QUERY 0x0082 +#define UDP_SRV_SYSTEM_MESSAGE 0x01C2 +#define UDP_SRV_ONLINE_MESSAGE 0x0104 +#define UDP_SRV_GO_AWAY 0x00F0 +#define UDP_SRV_TRY_AGAIN 0x00FA +#define UDP_SRV_FORCE_DISCONNECT 0x0028 +#define UDP_SRV_MULTI_PACKET 0x0212 +#define UDP_SRV_WRONG_PASSWORD 0x0064 +#define UDP_SRV_INVALID_UIN 0x012C +#define UDP_SRV_META_USER 0x03DE +#define UDP_SRV_RAND_USER 0x024E +#define UDP_SRV_AUTH_UPDATE 0x01F4 + +#define META_CMD_SET_INFO 1000 +#define META_CMD_SET_HOMEPAGE 1020 +#define META_CMD_SET_ABOUT 1030 +#define META_CMD_SET_SECURE 1060 +#define META_CMD_SET_PASS 1070 +#define META_CMD_REQ_INFO 1200 +#define META_SRV_RES_INFO 100 +#define META_SRV_RES_HOMEPAGE 120 +#define META_SRV_RES_ABOUT 130 +#define META_SRV_RES_SECURE 160 +#define META_SRV_RES_PASS 170 +#define META_SRV_USER_INFO 200 +#define META_SRV_USER_WORK 210 +#define META_SRV_USER_MORE 220 +#define META_SRV_USER_ABOUT 230 +#define META_SRV_USER_INTERESTS 240 +#define META_SRV_USER_AFFILIATIONS 250 +#define META_SRV_USER_HPCATEGORY 270 +#define META_SRV_USER_FOUND 410 + +#define META_SRV_SUCCESS 10 +#define META_SRV_FAILURE 50 + +#define TYPE_MSG 0x0001 +#define TYPE_CHAT 0x0002 +#define TYPE_FILE 0x0003 +#define TYPE_URL 0x0004 +#define TYPE_AUTH_REQ 0x0006 +#define TYPE_AUTH 0x0008 +#define TYPE_ADDED 0x000C +#define TYPE_WEBPAGER 0x000D +#define TYPE_EXPRESS 0x000E +#define TYPE_CONTACT 0x0013 +#define TYPE_MASS_MASK 0x8000 + +#define LOGIN_X1_DEF 0x00000098 +/*#define LOGIN_X1_DEF 0x000000D5*/ +#define LOGIN_X3_DEF 0x00000003 +/*#define LOGIN_X3_DEF 0x00000006*/ +#define LOGIN_X4_DEF 0x00000000 +#define LOGIN_X5_DEF 0x00980010 +/*#define LOGIN_X5_DEF 0x00D50008*/ +#define LOGIN_X6_DEF 0x00000050 +#define LOGIN_X7_DEF 0x00000003 +#define LOGIN_X8_DEF 0x00000000 + +#define LOGIN_SNDONLY_TCP 0x02 +#define LOGIN_SNDRCV_TCP 0x04 +#define LOGIN_NO_TCP 0x06 + +void icq_SendGotMessages(ICQLINK *link); +void icq_SendLogin1(ICQLINK *link); +void icq_StatusUpdate(ICQLINK *link, icq_Packet*); +void icq_AckSrv(ICQLINK *link, int seq); +void icq_HandleUserOffline(ICQLINK *link, icq_Packet*); +void icq_HandleUserOnline(ICQLINK *link, icq_Packet*); +void icq_DoMsg(ICQLINK *link, DWORD type, WORD len, char *data, DWORD uin, + BYTE hour, BYTE minute, BYTE day, BYTE month, WORD year); +int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet*); +int icq_UDPSockWrite(ICQLINK *link, icq_Packet*); +int icq_UDPSockRead(ICQLINK *link, icq_Packet*); +void icq_ServerResponse(ICQLINK *link, icq_Packet*); +void icq_HandleMultiPacket(ICQLINK *link, icq_Packet*); + +void icq_UDPAck(ICQLINK *link, int seq); +WORD icq_UDPSendMessage(ICQLINK *link, DWORD uin, const char *text); +WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr); + +#endif /* _UDP_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/udphandle.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,887 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: udphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.28 2000/06/25 17:25:52 denis +icq_HandleMetaUserInfo() handles all (!) available in original icq2k +Meta User Info packets along with other useful Meta* packets. (WOW! ;) + +Revision 1.27 2000/05/10 18:54:43 denis +icq_Disconnect() now called before icq_Disconnected callback to +prevent high CPU usage in kicq's "reconnect on disconnect" code. + +Revision 1.26 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.25 2000/02/07 02:48:15 bills +changed log message in HandleUserOnline + +Revision 1.24 2000/01/16 03:59:10 bills +reworked list code so list_nodes don't need to be inside item structures, +removed strlist code and replaced with generic list calls + +Revision 1.23 1999/12/27 11:12:37 denis +icq_UpdateMetaInfoSecurity() added for setting "My authorization is +required", "Web Aware" and "IP Publishing". + +Revision 1.22 1999/12/14 03:37:06 bills +removed old real_ip->ip masq hack, added store to remote_real_ip in +icq_ContactItem + +Revision 1.21 1999/12/12 18:03:58 denis +Authorization Request packet handling fixed. + +Revision 1.20 1999/11/29 17:18:31 denis +icq_DoMsg() redone using string lists. + +Revision 1.18 1999/11/11 15:10:32 guruz +- Added Base for Webpager Messages. Please type "make fixme" +- Removed Segfault when kicq is started the first time + +Revision 1.17 1999/10/14 11:44:04 denis +Cleanups. + +Revision 1.16 1999/09/29 17:16:08 denis +MailExpress message handler started. + +Revision 1.15 1999/07/18 20:23:54 bills +fixed tcp port bug in icq_HandleUserOnline, changed to use new byte-order +& contact list functions + +Revision 1.14 1999/07/16 15:46:02 denis +Cleaned up. + +Revision 1.13 1999/07/16 12:40:55 denis +ICQ UDP v5 implemented. +Encription for ICQ UDP v5 implemented. +icq_Packet* unified interface for UDP packets implemented. +Multipacket support of ICQ UDP v5 support added. + +Revision 1.12 1999/07/12 15:13:45 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.11 1999/07/03 06:46:54 lord +converting icq_userOnline callback parameters to correct +byte order. + +Revision 1.10 1999/07/03 02:29:46 bills +added code to HandleUserOnline to update tcp_flag + +Revision 1.9 1999/04/29 09:40:54 denis +Unsuccessful attempt to implement web presence (webaware) feature + +Revision 1.8 1999/04/18 01:58:37 bills +changed icq_SrvAck call to icq_RequestNotify + +Revision 1.7 1999/04/17 19:26:49 bills +removed *_link entries from icq_ContactItem, including cleaup/init code + +Revision 1.6 1999/04/14 15:05:39 denis +Cleanups for "strict" compiling (-ansi -pedantic) +Switched from icq_Log callback to icq_Fmt function. + +Revision 1.5 1999/04/05 18:47:23 bills +initial chat support implemented + +Revision 1.4 1999/03/31 01:39:50 bills +added handling of tcp_flag in HandleLogin + +Revision 1.3 1999/03/28 03:35:17 bills +fixed function names so icqlib compiles, fixed bug in HandleUserOnline +(remote_ip and remote_real_ip were not evaluating correctly), added +hack so I can test using local network + +Revision 1.2 1999/03/25 22:25:02 bills +modified icq_HandleUserOnline & Offline for new message_link + +Revision 1.1 1999/03/24 11:37:38 denis +Underscored files with TCP stuff renamed. +TCP stuff cleaned up +Function names changed to corresponding names. +icqlib.c splitted to many small files by subject. +C++ comments changed to ANSI C comments. + +*/ + +#include <stdlib.h> + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "udp.h" +#include "icqpacket.h" +#include "queue.h" +#include "icqbyteorder.h" +#include "list.h" + +int icq_SplitFields(list *strList, const char *str) +{ + char *tmpBuf, *tmp, *ptr; + int count = 0; + + tmpBuf = (char*)malloc(strlen(str)+1); + strcpy(tmpBuf, str); + ptr = tmpBuf; + + while(ptr) + { + char *p; + tmp = strchr(ptr, 0xFE); + if(tmp != 0L) + { + *tmp = 0; + tmp++; + } + count++; + p = (char *)malloc(strlen(ptr)+1); + strcpy(p, ptr); + list_enqueue(strList, p); + ptr = tmp; + } + + free(tmpBuf); + return count; +} + +void icq_DoMsg(ICQLINK *link, DWORD type, WORD len, char *data, DWORD uin, BYTE hour, + BYTE minute, BYTE day, BYTE month, WORD year) +{ + list *strList; + + strList = list_new(); + switch(type) + { + case TYPE_ADDED: + /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail */ + if(icq_SplitFields(strList, data)!=4) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + return; + } + icq_RusConv("wk", list_at(strList, 0)); /* Nick */ + icq_RusConv("wk", list_at(strList, 1)); /* FName */ + icq_RusConv("wk", list_at(strList, 2)); /* LName */ + icq_RusConv("wk", list_at(strList, 3)); /* EMail */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu has added you to their contact list, " + "Nick: %s, First Name: %s, Last Name: %s, EMail: %s\n", + uin, list_at(strList, 0), list_at(strList, 1), + list_at(strList, 2), list_at(strList, 3)); + if(link->icq_RecvAdded) + (*link->icq_RecvAdded)(link, uin, hour, minute, day, month, year, + list_at(strList, 0), list_at(strList, 1), + list_at(strList, 2), list_at(strList, 3)); + break; + case TYPE_AUTH_REQ: + /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail, 0xFE, 0, 0xFE, Reason */ + if(icq_SplitFields(strList, data)!=6) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + return; + } + icq_RusConv("wk", list_at(strList, 0)); /* Nick */ + icq_RusConv("wk", list_at(strList, 1)); /* FName */ + icq_RusConv("wk", list_at(strList, 2)); /* LName */ + icq_RusConv("wk", list_at(strList, 3)); /* EMail */ + icq_RusConv("wk", list_at(strList, 5)); /* Reason */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu has requested your authorization to be added to " + "their contact list, Nick: %s, First Name: %s, Last Name: %s, " + "EMail: %s, Reason: %s\n", uin, list_at(strList, 0), list_at(strList, 1), + list_at(strList, 2), list_at(strList, 3), list_at(strList, 4)); + if(link->icq_RecvAuthReq) + (*link->icq_RecvAuthReq)(link, uin, hour, minute, day, month, year, list_at(strList, 0), + list_at(strList, 1), list_at(strList, 2), + list_at(strList, 3), list_at(strList, 5)); + break; + case TYPE_URL: + /* Format: Description, 0xFE, URL */ + if(icq_SplitFields(strList, data)!=2) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + return; + } + icq_RusConv("wk", list_at(strList, 0)); /* Description */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "URL received from %lu, URL: %s, Description: %s\n", + uin, list_at(strList, 1), list_at(strList, 0)); + if(link->icq_RecvURL) + (*link->icq_RecvURL)(link, uin, hour, minute, day, month, year, list_at(strList, 1), + list_at(strList, 0)); + break; + case TYPE_WEBPAGER: + /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, + * Reason(3), 0xFE, Message with IP & Subject */ + if(icq_SplitFields(strList, data)!=6) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + return; + } + icq_RusConv("wk", list_at(strList, 0)); /* Nick */ + icq_RusConv("wk", list_at(strList, 5)); /* Message */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "WebPager message received, Nick: %s, EMail: %s, " + "Message:\n%s\n", list_at(strList, 0), list_at(strList, 3), + list_at(strList, 5)); + if(link->icq_RecvWebPager) + (*link->icq_RecvWebPager)(link, hour, minute, day, month, year, list_at(strList, 0), + list_at(strList, 3), list_at(strList, 5)); + break; + case TYPE_EXPRESS: + /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, + * Reason(3), 0xFE, Message Subject */ + if(icq_SplitFields(strList, data)!=6) + { + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + return; + } + icq_RusConv("wk", list_at(strList, 0)); /* Nick */ + icq_RusConv("wk", list_at(strList, 5)); /* Message */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "MailExpress message received, Nick: %s, EMail: %s, " + "Message:\n%s\n", list_at(strList, 0), list_at(strList, 3), + list_at(strList, 5)); + if(link->icq_RecvMailExpress) + (*link->icq_RecvMailExpress)(link, hour, minute, day, month, year, list_at(strList, 0), + list_at(strList, 3), list_at(strList, 5)); + break; + default: + icq_RusConv("wk", data); /* Entire message */ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Instant message type %i from %lu:\n%s\n", type, uin, data); + if(link->icq_RecvMessage) + (*link->icq_RecvMessage)(link, uin, hour, minute, day, month, year, data); + } + list_delete(strList, free); +} + +void icq_HandleInfoReply(ICQLINK *link, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4; + DWORD uin; + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + ptr2 = icq_PacketReadStringNew(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Info reply for %lu\n", uin); + if(link->icq_InfoReply) + (*link->icq_InfoReply)(link, uin, ptr1, ptr2, ptr3, ptr4, icq_PacketRead8(p)); + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); +} + +void icq_HandleExtInfoReply(ICQLINK *link, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5; + DWORD uin; + WORD cnt_code, age; + char cnt_stat, gender; + + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + cnt_code = icq_PacketRead16(p); + cnt_stat = icq_PacketRead8(p); + ptr2 = icq_PacketReadStringNew(p); + age = icq_PacketRead16(p); + gender = icq_PacketRead8(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + ptr5 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + icq_RusConv("wk", ptr5); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Extended info reply for %lu\n", uin); + if(link->icq_ExtInfoReply) + (*link->icq_ExtInfoReply)(link, uin, (char*)ptr1, cnt_code, cnt_stat, (char*)ptr2, age, + gender, (char*)ptr3, (char*)ptr4, (char*)ptr5); + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); + free(ptr5); +} + +void icq_HandleSearchReply(ICQLINK *link, icq_Packet *p) +{ + char *ptr1, *ptr2, *ptr3, *ptr4, auth; + DWORD uin; + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + ptr1 = icq_PacketReadStringNew(p); + ptr2 = icq_PacketReadStringNew(p); + ptr3 = icq_PacketReadStringNew(p); + ptr4 = icq_PacketReadStringNew(p); + icq_RusConv("wk", ptr1); + icq_RusConv("wk", ptr2); + icq_RusConv("wk", ptr3); + icq_RusConv("wk", ptr4); + auth = icq_PacketRead8(p); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "User found %lu, Nick: %s, First Name: %s, Last Name: %s, " + "EMail: %s, Auth: %s\n", uin, ptr1, ptr2, ptr3, ptr4, auth==1?"no":"yes"); + if(link->icq_UserFound) + (*link->icq_UserFound)(link, uin, (char*)ptr1, (char*)ptr2, (char*)ptr3, (char*)ptr4, auth); + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); + free(ptr1); + free(ptr2); + free(ptr3); + free(ptr4); +} + +/************************************************ +This is called when a user goes offline +*************************************************/ +void icq_HandleUserOffline(ICQLINK *link, icq_Packet *p) +{ + DWORD remote_uin; + icq_ContactItem *ptr; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "User %lu logged off\n", remote_uin); + if(link->icq_UserOffline) + (*link->icq_UserOffline)(link, remote_uin); + + ptr=icq_ContactFind(link, remote_uin); + if(ptr) + { + ptr->remote_ip = 0; + ptr->remote_port = 0; + } + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); +} + +void icq_HandleUserOnline(ICQLINK *link, icq_Packet *p) +{ + DWORD remote_uin, new_status, remote_ip, remote_real_ip; + DWORD remote_port; /* Why Mirabilis used 4 bytes for port? */ + BYTE tcp_flag; + icq_ContactItem *ptr; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + remote_ip = ntohl(icq_PacketRead32n(p)); /* icqtohl() */ + remote_port = icqtohl(icq_PacketRead32n(p)); + remote_real_ip = ntohl(icq_PacketRead32n(p)); /* icqtohl() */ + tcp_flag = icq_PacketRead8(p); + new_status = icq_PacketRead32(p); + + icq_FmtLog(link, ICQ_LOG_MESSAGE, + "User %lu (%s = 0x%X) logged on. tcp_flag=0x%X IP=%08X, real IP=%08X, port=%d\n", + remote_uin, icq_ConvertStatus2Str(new_status), new_status, tcp_flag, remote_ip, + remote_real_ip, remote_port); + if(link->icq_UserOnline) + (*link->icq_UserOnline)(link, remote_uin, new_status, remote_ip, remote_port, remote_real_ip, tcp_flag); + + ptr=icq_ContactFind(link, remote_uin); + if(ptr) + { + ptr->remote_ip=remote_ip; + ptr->remote_real_ip=remote_real_ip; + ptr->remote_port = remote_port; + ptr->tcp_flag = tcp_flag; + } + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); +} + +void icq_HandleStatusChange(ICQLINK *link, icq_Packet *p) +{ + unsigned long remote_uin, new_status; + + icq_PacketGotoUDPInData(p, 0); + remote_uin = icq_PacketRead32(p); + new_status = icq_PacketRead32(p); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu changed status to %s (0x%X)\n", remote_uin, + icq_ConvertStatus2Str(new_status), new_status); + if(link->icq_UserStatusUpdate) + (*link->icq_UserStatusUpdate)(link, remote_uin, new_status); + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); +} + +void icq_HandleMetaUserInfo(ICQLINK *link, icq_Packet *p) +{ + unsigned short subcmd, country, seq2, age, occupation, wcountry; + unsigned char res, auth, timezone, webaware, hideip, gender; + unsigned char *nick, *first, *last, *email, *about, *city; + unsigned char *pri_eml, *sec_eml, *old_eml; + unsigned char *phone, *fax, *street, *cellular, *state; + unsigned char *wcity, *wstate, *wphone, *wfax, *waddress; + unsigned char *company, *department, *job, *whomepage; + unsigned char *homepage; + unsigned char byear, bmonth, bday, lang1, lang2, lang3, inum, i; + unsigned char anum, bnum, hnum; + unsigned long uin, zip, wzip; + unsigned char *empty = ""; + unsigned char *interests[4] = {0, 0, 0, 0}; + unsigned short icategory[4] = {0, 0, 0, 0}; + unsigned char *affiliations[4] = {0, 0, 0, 0}; + unsigned short acategory[4] = {0, 0, 0, 0}; + unsigned char *backgrounds[4] = {0, 0, 0, 0}; + unsigned short bcategory[4] = {0, 0, 0, 0}; + unsigned char *hpcat[4] = {0, 0, 0, 0}; + unsigned short hcategory[4] = {0, 0, 0, 0}; + + seq2 = icq_PacketReadUDPInSeq2(p); + icq_PacketGotoUDPInData(p, 0); + subcmd = icq_PacketRead16(p); + res = icq_PacketRead8(p); + if(res == META_SRV_FAILURE) + { + icq_FmtLog(link, ICQ_LOG_WARNING, "META failure\n"); + if(link->icq_RequestNotify) + (*link->icq_RequestNotify)(link, seq2, ICQ_NOTIFY_FAILED, sizeof(subcmd), &subcmd); + } + else + switch(subcmd) + { + case META_SRV_USER_FOUND: + uin = icq_PacketRead32(p); + nick = icq_PacketReadStringNew(p); + first = icq_PacketReadStringNew(p); + last = icq_PacketReadStringNew(p); + email = icq_PacketReadStringNew(p); + auth = icq_PacketRead8(p); + icq_PacketRead16(p); // ??? + icq_PacketRead32(p); // ??? + icq_RusConv("wk", nick); + icq_RusConv("wk", first); + icq_RusConv("wk", last); + icq_RusConv("wk", email); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Found %lu, Nick: %s, First Name: %s, "\ + "Last Name: %s, EMail: %s, Auth: %s\n", seq2, uin, nick, first, last, + email, auth==1?"no":"yes"); + if(link->icq_MetaUserFound) + (*link->icq_MetaUserFound)(link, seq2, uin, nick, first, last, email, auth); + free(nick); + free(first); + free(last); + free(email); + break; + case META_SRV_USER_INFO: // finished! + nick = icq_PacketReadStringNew(p); + first = icq_PacketReadStringNew(p); + last = icq_PacketReadStringNew(p); + pri_eml = icq_PacketReadStringNew(p); + sec_eml = icq_PacketReadStringNew(p); + old_eml = icq_PacketReadStringNew(p); + city = icq_PacketReadStringNew(p); + state = icq_PacketReadStringNew(p); + phone = icq_PacketReadStringNew(p); + fax = icq_PacketReadStringNew(p); + street = icq_PacketReadStringNew(p); + cellular = icq_PacketReadStringNew(p); + zip = icq_PacketRead32(p); + country = icq_PacketRead16(p); + timezone = icq_PacketRead8(p); // +1 = -30min, -1 = +30min (-4 = GMT+0200) + auth = icq_PacketRead8(p); // 1 - no auth required, 0 - required + webaware = icq_PacketRead8(p); // 1 - yes, 0 - no + hideip = icq_PacketRead8(p); // 1 - yes, 0 - no + icq_RusConv("wk", nick); + icq_RusConv("wk", first); + icq_RusConv("wk", last); + icq_RusConv("wk", pri_eml); + icq_RusConv("wk", sec_eml); + icq_RusConv("wk", old_eml); + icq_RusConv("wk", city); + icq_RusConv("wk", state); + icq_RusConv("wk", phone); + icq_RusConv("wk", fax); + icq_RusConv("wk", street); + icq_RusConv("wk", cellular); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Info: %s, %s, %s, "\ + "%s, %s, %s, %s, %s, %s, %s, %s, %s, %lu, %s, %i, %s, %s, %s\n", + nick, first, last, pri_eml, sec_eml, old_eml, city, state, phone, + fax, street, cellular, zip, icq_GetCountryName(country), timezone, + auth?"false":"true", webaware?"true":"false", hideip?"true":"false"); + if(link->icq_MetaUserInfo) + (*link->icq_MetaUserInfo)(link, seq2, nick, first, last, pri_eml, sec_eml, + old_eml, city, state, phone, fax, street, cellular, + zip, country, timezone, auth, webaware, hideip); + free(nick); + free(first); + free(last); + free(pri_eml); + free(sec_eml); + free(old_eml); + free(city); + free(state); + free(phone); + free(fax); + free(street); + free(cellular); + break; + case META_SRV_USER_WORK: // finished! + wcity = icq_PacketReadStringNew(p); + wstate = icq_PacketReadStringNew(p); + wphone = icq_PacketReadStringNew(p); + wfax = icq_PacketReadStringNew(p); + waddress = icq_PacketReadStringNew(p); + wzip = icq_PacketRead32(p); + wcountry = icq_PacketRead16(p); // icq_GetCountryName() + company = icq_PacketReadStringNew(p); + department = icq_PacketReadStringNew(p); + job = icq_PacketReadStringNew(p); + occupation = icq_PacketRead16(p); // icq_GetMetaOccupationName() + whomepage = icq_PacketReadStringNew(p); + icq_RusConv("wk", wcity); + icq_RusConv("wk", wstate); + icq_RusConv("wk", wphone); + icq_RusConv("wk", wfax); + icq_RusConv("wk", waddress); + icq_RusConv("wk", company); + icq_RusConv("wk", department); + icq_RusConv("wk", job); + icq_RusConv("wk", whomepage); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Work: %s, %s, %s, "\ + "%s, %s, %lu, %s, %s, %s, %s, %s, %s\n", wcity, wstate, + wphone, wfax, waddress, wzip, icq_GetCountryName(wcountry), + company, department, job, icq_GetMetaOccupationName(occupation), + whomepage); + if(link->icq_MetaUserWork) + (*link->icq_MetaUserWork)(link, seq2, wcity, wstate, wphone, wfax, + waddress, wzip, wcountry, company, department, + job, occupation, whomepage); + free(wcity); + free(wstate); + free(wphone); + free(wfax); + free(waddress); + free(company); + free(department); + free(job); + free(whomepage); + break; + case META_SRV_USER_MORE: // finished! + age = icq_PacketRead16(p); // 0xFFFF - not entered + gender = icq_PacketRead8(p); // 1 - female, 2 - male + homepage = icq_PacketReadStringNew(p); + byear = icq_PacketRead8(p); // starting from 1900 + bmonth = icq_PacketRead8(p); + bday = icq_PacketRead8(p); + lang1 = icq_PacketRead8(p); // icq_GetMetaLanguageName() + lang2 = icq_PacketRead8(p); // icq_GetMetaLanguageName() + lang3 = icq_PacketRead8(p); // icq_GetMetaLanguageName() + icq_RusConv("wk", homepage); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User More: %i, %s, %s, "\ + "%02i/%02i/%04i, %s, %s, %s\n", age, + gender==1?"female":gender==2?"male":"not entered", + homepage, bday, bmonth, byear+1900, icq_GetMetaLanguageName(lang1), + icq_GetMetaLanguageName(lang2), icq_GetMetaLanguageName(lang3)); + if(link->icq_MetaUserMore) + (*link->icq_MetaUserMore)(link, seq2, age, gender, homepage, byear, + bmonth, bday, lang1, lang2, lang3); + free(homepage); + break; + case META_SRV_USER_ABOUT: // finished! + about = icq_PacketReadStringNew(p); + icq_RusConv("wk", about); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User About: %s\n", about); + if(link->icq_MetaUserAbout) + (*link->icq_MetaUserAbout)(link, seq2, about); + free(about); + break; + case META_SRV_USER_INTERESTS: // finished! + inum = icq_PacketRead8(p); + for(i=0; i<inum && i<4; i++) + { + icategory[i] = icq_PacketRead16(p); + interests[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", interests[i]); + } + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Interests: %i, %i - %s, "\ + "%i - %s, %i - %s, %i - %s\n", inum, icategory[0], + interests[0]?interests[0]:empty, icategory[1], interests[1]?interests[1]:empty, + icategory[2], interests[2]?interests[2]:empty, icategory[3], + interests[3]?interests[3]:empty); + if(link->icq_MetaUserInterests) + (*link->icq_MetaUserInterests)(link, seq2, inum, icategory[0], interests[0], + icategory[1], interests[1], icategory[2], + interests[2], icategory[3], interests[3]); + for(i=0; i<inum && i<4; i++) + free(interests[i]); + break; + case META_SRV_USER_AFFILIATIONS: // finished! + bnum = icq_PacketRead8(p); + for(i=0; i<bnum && i<4; i++) + { + bcategory[i] = icq_PacketRead16(p); // icq_GetMetaBackgroundName() + backgrounds[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", backgrounds[i]); + } + anum = icq_PacketRead8(p); + for(i=0; i<anum && i<4; i++) + { + acategory[i] = icq_PacketRead16(p); // icq_GetMetaAffiliationName() + affiliations[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", affiliations[i]); + } + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Affiliations: %i, %s - %s, "\ + "%s - %s, %s - %s, %s - %s; Backgrounds: %i, %s - %s, %s - %s, "\ + "%s - %s, %s - %s\n", anum, + icq_GetMetaAffiliationName(acategory[0]), affiliations[0]?affiliations[0]:empty, + icq_GetMetaAffiliationName(acategory[1]), affiliations[1]?affiliations[1]:empty, + icq_GetMetaAffiliationName(acategory[2]), affiliations[2]?affiliations[2]:empty, + icq_GetMetaAffiliationName(acategory[3]), affiliations[3]?affiliations[3]:empty, + bnum, icq_GetMetaBackgroundName(bcategory[0]), backgrounds[0]?backgrounds[0]:empty, + icq_GetMetaBackgroundName(bcategory[1]), backgrounds[1]?backgrounds[1]:empty, + icq_GetMetaBackgroundName(bcategory[2]), backgrounds[2]?backgrounds[2]:empty, + icq_GetMetaBackgroundName(bcategory[3]), backgrounds[3]?backgrounds[3]:empty); + if(link->icq_MetaUserAffiliations) + (*link->icq_MetaUserAffiliations)(link, seq2, anum, acategory[0], + affiliations[0], acategory[1], affiliations[1], acategory[2], + affiliations[2], acategory[3], affiliations[3], bnum, + bcategory[0], backgrounds[0], bcategory[1], backgrounds[1], + bcategory[2], backgrounds[2], bcategory[3], backgrounds[3]); + for(i=0; i<bnum && i<4; i++) + free(backgrounds[i]); + for(i=0; i<anum && i<4; i++) + free(affiliations[i]); + break; + case META_SRV_USER_HPCATEGORY: // finished! + hnum = icq_PacketRead8(p); + for(i=0; i<hnum && i<1; i++) + { + hcategory[i] = icq_PacketRead16(p); + hpcat[i] = icq_PacketReadStringNew(p); + icq_RusConv("wk", hpcat[i]); + } + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Homepage Category: %i, %i - %s\n", + hnum, hcategory[0], hpcat[0]); + if(link->icq_MetaUserHomePageCategory) + (*link->icq_MetaUserHomePageCategory)(link, seq2, hnum, hcategory[0], hpcat[0]?hpcat[0]:empty); + for(i=0; i<hnum && i<1; i++) + free(hpcat[i]); + break; + case META_SRV_RES_INFO: + case META_SRV_RES_HOMEPAGE: + case META_SRV_RES_ABOUT: + case META_SRV_RES_SECURE: + case META_SRV_RES_PASS: + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META success\n"); + if(link->icq_RequestNotify) + (*link->icq_RequestNotify)(link, seq2, ICQ_NOTIFY_SUCCESS, sizeof(subcmd), &subcmd); + break; + default: + icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User - 0x%04X\n", subcmd); + icq_PacketUDPDump(p); + break; + } + icq_UDPAck(link, icq_PacketReadUDPInSeq1(p)); +} + +void icq_HandleMultiPacket(ICQLINK *link, icq_Packet *p) +{ + icq_Packet *tmp; + int num, i; + icq_PacketGotoUDPInData(p, 0); + num = icq_PacketRead8(p); + + icq_FmtLog(link, ICQ_LOG_MESSAGE, "MultiPacket: %i packets\n", num); + + for(i = 0; i < num; i++) + { + tmp = icq_PacketNew(); + tmp->length = icq_PacketRead16(p); + memcpy(tmp->data, &(p->data[p->cursor]), tmp->length); + icq_PacketAdvance(p, tmp->length); + icq_ServerResponse(link, tmp); + icq_PacketDelete(tmp); + } +} + +void icq_ServerResponse(ICQLINK *link, icq_Packet *p) +{ + time_t cur_time; + struct tm *tm_str; + int len; + struct in_addr in_a; + DWORD uin; + WORD year, type, seq, cmd; + BYTE month, day, hour, minute; + + seq = icq_PacketReadUDPInSeq1(p); + cmd = icq_PacketReadUDPInCmd(p); + + if(icq_PacketReadUDPInVer(p) == 5) /* We understand only V5 packets! */ + { + switch(cmd) + { + case UDP_SRV_ACK: + icq_FmtLog(link, ICQ_LOG_MESSAGE, "The server acknowledged the command\n"); + if(link->icq_RequestNotify) + { + (*link->icq_RequestNotify)(link, seq, ICQ_NOTIFY_ACK, 0, 0); + (*link->icq_RequestNotify)(link, seq, ICQ_NOTIFY_SUCCESS, 0, 0); + } + icq_UDPQueueDelSeq(link, seq); + if(link->icq_SetTimeout) + link->icq_SetTimeout(link, icq_UDPQueueInterval(link)); + break; + case UDP_SRV_MULTI_PACKET: + icq_HandleMultiPacket(link, p); + break; + case UDP_SRV_NEW_UIN: + uin = icq_PacketReadUDPInUIN(p); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "The new uin is %lu\n", uin); + icq_UDPAck(link, seq); + if(link->icq_NewUIN) + (*link->icq_NewUIN)(link, uin); + break; + case UDP_SRV_LOGIN_REPLY: + icq_PacketGotoUDPInData(p, 0); + link->icq_OurIP = ntohl(icq_PacketRead32n(p)); +/* icq_OurIp = icq_PacketRead32(p); */ + in_a.s_addr = htonl(link->icq_OurIP); + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Login successful, UIN: %lu, IP: %s\n", + link->icq_Uin, inet_ntoa(in_a)); + icq_UDPAck(link, seq); + icq_SendLogin1(link); + icq_SendContactList(link); + icq_SendVisibleList(link); + if(link->icq_Logged) + (*link->icq_Logged)(link); + break; + case UDP_SRV_OFFLINE_MESSAGE: /* Offline message through the server */ + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + year = icq_PacketRead16(p); + month = icq_PacketRead8(p); + day = icq_PacketRead8(p); + hour = icq_PacketRead8(p); + minute = icq_PacketRead8(p); + type = icq_PacketRead16(p); + len = icq_PacketRead16(p); + icq_DoMsg(link, type, len, (char*)&p->data[p->cursor], uin, hour, minute, day, month, year); + icq_UDPAck(link, seq); + break; + case UDP_SRV_X1: /* unknown message sent after login*/ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X1 (Begin messages)\n"); + icq_UDPAck(link, seq); + break; + case UDP_SRV_X2: /* unknown message sent after login*/ + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X2 (Done old messages)\n"); + icq_UDPAck(link, seq); + icq_SendGotMessages(link); + break; + case UDP_SRV_INFO_REPLY: + icq_HandleInfoReply(link, p); + break; + case UDP_SRV_EXT_INFO_REPLY: + icq_HandleExtInfoReply(link, p); + break; + case UDP_SRV_USER_ONLINE: + icq_HandleUserOnline(link, p); + break; + case UDP_SRV_USER_OFFLINE: + icq_HandleUserOffline(link, p); + break; + case UDP_SRV_TRY_AGAIN: + icq_FmtLog(link, ICQ_LOG_WARNING, "Server is busy, please try again\n"); + icq_Login(link, link->icq_Status); + break; + case UDP_SRV_STATUS_UPDATE: + icq_HandleStatusChange(link, p); + break; + case UDP_SRV_GO_AWAY: + icq_FmtLog(link, ICQ_LOG_ERROR, "Server has forced us to disconnect\n"); + if(link->icq_Disconnected) + (*link->icq_Disconnected)(link); + break; + case UDP_SRV_END_OF_SEARCH: + icq_FmtLog(link, ICQ_LOG_MESSAGE, "Search done\n"); + if(link->icq_SearchDone) + (*link->icq_SearchDone)(link); + icq_UDPAck(link, seq); + break; + case UDP_SRV_USER_FOUND: + icq_HandleSearchReply(link, p); + break; + case UDP_SRV_ONLINE_MESSAGE: /* Online message through the server */ + cur_time = time(0L); + tm_str = localtime(&cur_time); + icq_PacketGotoUDPInData(p, 0); + uin = icq_PacketRead32(p); + type = icq_PacketRead16(p); + len = icq_PacketRead16(p); + icq_DoMsg(link, type, len, (char*)&p->data[p->cursor], uin, tm_str->tm_hour, + tm_str->tm_min, tm_str->tm_mday, tm_str->tm_mon+1, tm_str->tm_year+1900); + icq_UDPAck(link, seq); + break; + case UDP_SRV_WRONG_PASSWORD: + icq_FmtLog(link, ICQ_LOG_ERROR, "Wrong password\n"); + if(link->icq_WrongPassword) + (*link->icq_WrongPassword)(link); + icq_UDPAck(link, seq); + break; + case UDP_SRV_INVALID_UIN: + icq_FmtLog(link, ICQ_LOG_WARNING, "Invalid UIN\n"); + if(link->icq_InvalidUIN) + (*link->icq_InvalidUIN)(link); + icq_UDPAck(link, seq); + break; + case UDP_SRV_META_USER: + icq_HandleMetaUserInfo(link, p); + break; + default: /* commands we dont handle yet */ + icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled message %04x, Version: %x, " + "Sequence: %04x, Size: %d\n", cmd, icq_PacketReadUDPInVer(p), + seq, p->length); + icq_UDPAck(link, seq); /* fake like we know what we're doing */ + break; + } + } + else + { + icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled message %04x, Version: %x, " + "Sequence: %04x, Size: %d\n", cmd, icq_PacketReadUDPInVer(p), + seq, p->length); + icq_UDPAck(link, seq); /* fake like we know what we're doing */ + } +} + +/****************************************** +Handles packets that the server sends to us. +*******************************************/ +void icq_HandleServerResponse(ICQLINK *link) +{ + WORD seq, cmd; + int s; + icq_Packet *p; + + p = icq_PacketNew(); + s = icq_UDPSockRead(link, p); + p->length = s; + if(s<=0) + { + icq_FmtLog(link, ICQ_LOG_FATAL, "Connection terminated\n"); + icq_Disconnect(link); + if(link->icq_Disconnected) + (*link->icq_Disconnected)(link); + } + seq = icq_PacketReadUDPInSeq1(p); + cmd = icq_PacketReadUDPInCmd(p); + if(icq_GetServMess(link, seq) && cmd != UDP_SRV_NEW_UIN && cmd != UDP_SRV_GO_AWAY && cmd != UDP_SRV_ACK) + { + icq_FmtLog(link, ICQ_LOG_WARNING, "Ignored a message cmd %04x, seq %04x\n", cmd, seq); + icq_UDPAck(link, seq); /* LAGGGGG!! */ + icq_PacketDelete(p); + return; + } + if(cmd != UDP_SRV_ACK) + icq_SetServMess(link, seq); + + icq_ServerResponse(link, p); + + icq_PacketDelete(p); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/util.c Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,541 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* +$Id: util.c 1162 2000-11-28 02:22:42Z warmenhoven $ +$Log$ +Revision 1.1 2000/11/28 02:22:42 warmenhoven +icq. whoop de doo + +Revision 1.32 2000/07/22 16:49:32 denis +Trinidad and Tobago country was added. + +Revision 1.31 2000/07/21 16:51:20 denis +All languages, possible in original icq were added. +Occupation array fixed. + +Revision 1.30 2000/07/20 09:58:59 denis +Occupation table corrected to comply with original ICQ. + +Revision 1.29 2000/07/04 07:25:29 pcadach +icq_FmtLog() crashed when it receives NULL at link argument. + +Revision 1.28 2000/06/30 13:59:43 denis +Slovak Republic country code fixed. + +Revision 1.27 2000/06/25 17:00:32 denis +icq_MetaOccupation[], icq_MetaPastBackgrounds[], +icq_MetaAffiliations[] and icq_MetaLanguages[] arrays were added along +with icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(), +icq_GetMetaAffiliationName() and icq_GetMetaLanguageName() functions +to access them. + +Revision 1.26 2000/05/21 17:42:51 denis +Bulgaria country code was added. Thanks to +"Napalm Death" <napalmbox@hotmail.com> + +Revision 1.25 2000/05/03 18:29:15 denis +Callbacks have been moved to the ICQLINK structure. + +Revision 1.24 2000/04/10 16:36:04 denis +Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> + +Revision 1.23 2000/04/05 14:37:02 denis +Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 +compatibility. + +Revision 1.22 2000/03/31 12:49:15 nofate +remove static variable + +Revision 1.21 1999/11/11 15:10:33 guruz +- Added Base for Webpager Messages. Please type "make fixme" +- Removed Segfault when kicq is started the first time + +Revision 1.20 1999/10/07 18:01:40 denis +Cleanups. + +Revision 1.19 1999/09/29 17:16:45 denis +Cleanups. + +Revision 1.18 1999/07/18 20:24:27 bills +removed old byte order and contact list functions + +Revision 1.17 1999/07/16 15:46:03 denis +Cleaned up. + +Revision 1.16 1999/07/16 12:04:49 denis +Status support changed. + +Revision 1.15 1999/07/12 15:13:46 cproch +- added definition of ICQLINK to hold session-specific global variabled + applications which have more than one connection are now possible +- changed nearly every function defintion to support ICQLINK parameter + +Revision 1.14 1999/04/17 19:20:35 bills +removed *_link entries from icq_ContactItem, including cleanup/init code + +Revision 1.13 1999/04/14 15:06:51 denis +Cleanups for "strict" compiling (-ansi -pedantic) + +*/ + +#include <stdlib.h> +#include <ctype.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include "icqtypes.h" +#include "icq.h" +#include "icqlib.h" +#include "stdpackets.h" +#include "util.h" +#include "stdarg.h" + +/* + * This list of countries should be sorted according to country code. + * When adding new country, please preserve the order! + */ +icq_ArrayType icq_Countries[] = { + {"USA",1}, + {"Russia",7}, + {"Egypt",20}, + {"South Africa",27}, + {"Greece",30}, + {"Netherlands",31}, + {"Belgium",32}, + {"France",33}, + {"Monaco",33}, + {"Spain",34}, + {"Hungary",36}, + {"Yugoslavia",38}, + {"Italy",39}, + {"San Marino",39}, + {"Vatican City",39}, + {"Romania",40}, + {"Liechtenstein",41}, + {"Switzerland",41}, + {"Czech Republic",42}, + {"Austria",43}, + {"UK",44}, + {"Denmark",45}, + {"Sweden",46}, + {"Norway",47}, + {"Poland",48}, + {"Germany",49}, + {"Peru",51}, + {"Mexico",52}, + {"Guantanomo Bay",53}, + {"Argentina",54}, + {"Brazil",55}, + {"Chile",56}, + {"Columbia",57}, + {"Venezuela",58}, + {"Malaysia",60}, + {"Australia",61}, + {"Indonesia",62}, + {"Philippines",63}, + {"New Zealand",64}, + {"Singapore",65}, + {"Thailand",66}, + {"Japan",81}, + {"South Korea",82}, + {"Vietnam",84}, + {"China",86}, + {"Turkey",90}, + {"India",91}, + {"Pakistan",92}, + {"Sri Lanka",94}, + {"Iran",98}, + {"Canada",107}, + {"Morocco",212}, + {"Algeria",213}, + {"Tunisia",216}, + {"Libya",218}, + {"Senegal",221}, + {"Mali",223}, + {"Ivory Coast",225}, + {"Liberia",231}, + {"Ghana",233}, + {"Nigeria",234}, + {"Cameroon",237}, + {"Gabon",241}, + {"Zaire",243}, + {"Ethiopia",251}, + {"Kenya",254}, + {"Tanzania",255}, + {"Zimbabwe",263}, + {"Namibia",264}, + {"Malawi",265}, + {"Aruba",297}, + {"Portugal",351}, + {"Luxembourg",352}, + {"Ireland",353}, + {"Iceland",354}, + {"Malta",356}, + {"Cyprus",357}, + {"Finland",358}, + {"Bulgaria",359}, + {"Ukraine",380}, + {"Belize",501}, + {"Guatemala",502}, + {"El Salvador",503}, + {"Honduras",504}, + {"Nicaragua",505}, + {"Costa Rice",506}, + {"Panama",507}, + {"Haiti",509}, + {"Guadeloupe",590}, + {"Bolivia",591}, + {"Guyana",592}, + {"Ecuador",593}, + {"Paraguay",595}, + {"French Antilles",596}, + {"Suriname",597}, + {"Uruguay",598}, + {"Netherlands Antilles",599}, + {"Saipan",670}, + {"Saipan",670}, + {"Guam",671}, + {"Papua New Guinea",675}, + {"Fiji",679}, + {"American Samoa",684}, + {"New Caledonia",687}, + {"French Polynesia",689}, + {"Hong Kong",852}, + {"Trinidad and Tobago",868}, + {"Bangladesh",880}, + {"Taiwan",886}, + {"Jordan",962}, + {"Iraq",964}, + {"Kuwait",965}, + {"Saudia Arabia",966}, + {"Yemen",967}, + {"Oman",968}, + {"United Arab Emirates",971}, + {"Israel",972}, + {"Bahrain",973}, + {"Qatar",974}, + {"Nepal",977}, + {"Slovak Republic",4201}, + {"Not entered",0xffff}, +}; + +icq_ArrayType icq_MetaOccupation[] = { + {"Academic", 1}, + {"Administrative", 2}, + {"Art/Entertainment", 3}, + {"College Student", 4}, + {"Computers", 5}, + {"Community & Social", 6}, + {"Education", 7}, + {"Engineering", 8}, + {"Financial Services", 9}, + {"Government", 10}, + {"High School Student", 11}, + {"Home", 12}, + {"ICQ - Providing Help", 13}, + {"Law", 14}, + {"Managerial", 15}, + {"Manufacturing", 16}, + {"Medical/Health", 17}, + {"Military", 18}, + {"Non-Government Organization", 19}, + {"Professional", 20}, + {"Retail", 21}, + {"Retired", 22}, + {"Science & Research", 23}, + {"Sports", 24}, + {"Technical", 25}, + {"University Student", 26}, + {"Web Building", 27}, + {"Other Services", 99}, +}; + +icq_ArrayType icq_MetaPastBackgrounds[] = { + {"Elementary School", 300}, + {"High School", 301}, + {"College", 302}, + {"University", 303}, + {"Military", 304}, + {"Past Work Place", 305}, + {"Past Organization", 306}, + {"Other", 399}, +}; + +icq_ArrayType icq_MetaAffiliations[] = { + {"Alumni Org.", 200}, + {"Charity Org.", 201}, + {"Club/Social Org.", 202}, + {"Community Org.", 203}, + {"Cultural Org.", 204}, + {"Fan Clubs", 205}, + {"Fraternity/Sorority", 206}, + {"Hobbyists Org.", 207}, + {"International Org.", 208}, + {"Nature and Environment Org.", 209}, + {"Professional Org.", 210}, + {"Scientific/Technical Org.", 211}, + {"Self Improvement Group", 212}, + {"Spiritual/Religious Org.", 213}, + {"Sports Org.", 214}, + {"Support Org.", 215}, + {"Trade and Business Org.", 216}, + {"Union", 217}, + {"Voluntary Org.", 218}, + {"Other", 299}, +}; + +icq_ArrayType icq_MetaLanguages[] = { + {"Not Entered", 0}, + {"Arabic", 1}, + {"Bhojpuri", 2}, + {"Bulgarian", 3}, + {"Burmese", 4}, + {"Cantonese", 5}, + {"Catalan", 6}, + {"Chinese", 7}, + {"Croatian", 8}, + {"Czech", 9}, + {"Danish", 10}, + {"Dutch", 11}, + {"English", 12}, + {"Esperanto", 13}, + {"Estonian", 14}, + {"Farsi", 15}, + {"Finnish", 16}, + {"French", 17}, + {"Gaelic", 18}, + {"German", 19}, + {"Greek", 20}, + {"Hebrew", 21}, + {"Hindi", 22}, + {"Hungarian", 23}, + {"Icelandic", 24}, + {"Indonesian", 25}, + {"Italian", 26}, + {"Japanese", 27}, + {"Khmer", 28}, + {"Korean", 29}, + {"Lao", 30}, + {"Latvian", 31}, + {"Lithuanian", 32}, + {"Malay", 33}, + {"Norwegian", 34}, + {"Polish", 35}, + {"Portuguese", 36}, + {"Romanian", 37}, + {"Russian", 38}, + {"Serbian", 39}, + {"Slovak", 40}, + {"Slovenian", 41}, + {"Somali", 42}, + {"Spanish", 43}, + {"Swahili", 44}, + {"Swedish", 45}, + {"Tagalog", 46}, + {"Tatar", 47}, + {"Thai", 48}, + {"Turkish", 49}, + {"Ukrainian", 50}, + {"Urdu", 51}, + {"Vietnamese", 52}, + {"Yiddish", 53}, + {"Yoruba", 54}, + {"Afrikaans", 55}, + {"Bosnian", 56}, + {"Persian", 57}, + {"Albanian", 58}, + {"Armenian", 59}, + {"Punjabi", 60}, + {"Chamorro", 61}, + {"Mongolian", 62}, + {"Mandarin", 63}, + {"Taiwaness", 64}, + {"Macedonian", 65}, + {"Sindhi", 66}, + {"Welsh", 67}, +}; + +void hex_dump(char *data, long size) +{ + long i; + long x; + int r=1; + char d[32]; + unsigned char bfr[64]; + for(i=0, x=0;;i++) + { + if(i<size) + { + if(x==0) + printf("%04lx: ", i); +#ifdef _WIN32 + sprintf(d, "%08x", data[i]); +#else + snprintf(d, 9, "%08x", data[i]); +#endif + printf("%c%c ", d[6], d[7]); + bfr[x]=data[i]; + if(bfr[x]<0x20) + bfr[x]='.'; + if(bfr[x]>0x7f) + bfr[x]='.'; + } + else + { + if(x==0) + break; + else + { + printf(" "); + bfr[x]=' '; + r=0; + } + } + x++; + if(!(x<16)) + { + bfr[x]=0; + printf("%s\n", bfr); + x=0; + if(!r) + break; + } + } +} + +/* simple mapping for udp status->tcp status translation function */ +struct icq_TCPStatusRec +{ + unsigned long udp_status; + long tcp_status; +} icq_TCPStatusMap[] = { + { STATUS_OFFLINE , 0 }, + { STATUS_ONLINE , ICQ_TCP_STATUS_ONLINE }, + { STATUS_INVISIBLE , ICQ_TCP_STATUS_INVISIBLE }, + { STATUS_NA , ICQ_TCP_STATUS_NA }, + { STATUS_FREE_CHAT , ICQ_TCP_STATUS_FREE_CHAT }, + { STATUS_OCCUPIED , ICQ_TCP_STATUS_OCCUPIED }, + { STATUS_AWAY , ICQ_TCP_STATUS_AWAY }, + { STATUS_DND , ICQ_TCP_STATUS_DND }, +}; + +long icq_TCPXlateStatus(unsigned long udp_status) +{ + unsigned int i; + for(i=0;i<sizeof(icq_TCPStatusMap)/sizeof(struct icq_TCPStatusRec);i++) + if(icq_TCPStatusMap[i].udp_status==udp_status) + return icq_TCPStatusMap[i].tcp_status; + /* warning: "couldn't find tcp status for %d, assuming 0", udp_status */ + return 0; +} + +void icq_FmtLog(ICQLINK *link, int level, const char *fmt, ...) +{ + char buffer[2048]; + va_list ap; + va_start(ap, fmt); + + if(!link) + return; +#ifdef _MSVC_ + _vsnprintf(buffer, 1024, fmt, ap); +#else + (void)vsnprintf(buffer, 1024, fmt, ap); +#endif + va_end(ap); + + if(link->icq_Log && icq_LogLevel>=level) + (*link->icq_Log)(link, time(0L), level, buffer); +} + +/** + * Following functions used by qsort and bsearch to + * compare 2 pointers to icq_ArrayType object. + */ +int array_code_compare(const void *x, const void *y) +{ + return ((icq_ArrayType*)x)->code - ((icq_ArrayType*)y)->code; +} + +const char *icq_GetCountryName(unsigned short code) +{ + icq_ArrayType *res,key; + + key.code=code; + res=bsearch(&key, icq_Countries, sizeof(icq_Countries)/sizeof(icq_ArrayType), + sizeof(icq_ArrayType), array_code_compare); + + return res?res->name:"Unknown"; +} + +const char *icq_GetMetaOccupationName(unsigned short code) +{ + icq_ArrayType *res,key; + + key.code=code; + res=bsearch(&key, icq_MetaOccupation, sizeof(icq_MetaOccupation)/sizeof(icq_ArrayType), + sizeof(icq_ArrayType), array_code_compare); + + return res?res->name:"Unknown"; +} + +const char *icq_GetMetaBackgroundName(unsigned short code) +{ + icq_ArrayType *res,key; + + key.code=code; + res=bsearch(&key, icq_MetaPastBackgrounds, sizeof(icq_MetaPastBackgrounds)/sizeof(icq_ArrayType), + sizeof(icq_ArrayType), array_code_compare); + + return res?res->name:"Unknown"; +} + +const char *icq_GetMetaAffiliationName(unsigned short code) +{ + icq_ArrayType *res,key; + + key.code=code; + res=bsearch(&key, icq_MetaAffiliations, sizeof(icq_MetaAffiliations)/sizeof(icq_ArrayType), + sizeof(icq_ArrayType), array_code_compare); + + return res?res->name:"Unknown"; +} + +const char *icq_GetMetaLanguageName(unsigned short code) +{ + icq_ArrayType *res,key; + + key.code=code; + res=bsearch(&key, icq_MetaLanguages, sizeof(icq_MetaLanguages)/sizeof(icq_ArrayType), + sizeof(icq_ArrayType), array_code_compare); + + return res?res->name:"Unknown"; +} + +/******************************************** +returns a string describing the status or +a "Error" if no such string exists +*********************************************/ +const char *icq_ConvertStatus2Str(unsigned long status) +{ + if((unsigned long)STATUS_OFFLINE == status) /* this because -1 & 0x01FF is not -1 */ + return "Offline"; + + if((status & STATUS_INVISIBLE) == STATUS_INVISIBLE) + return "Invisible"; + else if((status & STATUS_FREE_CHAT) == STATUS_FREE_CHAT) + return "Free for chat"; + else if((status & STATUS_DND) == STATUS_DND) + return "Do not disturb"; + else if((status & STATUS_OCCUPIED) == STATUS_OCCUPIED) + return "Occupied"; + else if((status & STATUS_NA) == STATUS_NA) + return "Not available"; + else if((status & STATUS_AWAY) == STATUS_AWAY) + return "Away"; + else if(!(status & 0x01FF)) + return "Online"; + else + return "Error"; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/util.h Tue Nov 28 02:22:42 2000 +0000 @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> + +#ifdef _WIN32 +#include <winsock.h> +#else +#include <netinet/in.h> +#endif + +#include "icqtypes.h" +#include "icq.h" + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE !FALSE +#endif + +void hex_dump(char *data, long size); + +WORD Chars_2_Word(unsigned char *buf); +DWORD Chars_2_DW(unsigned char *buf); +void DW_2_Chars(unsigned char *buf, DWORD num); +void Word_2_Chars(unsigned char *buf, WORD num); + +const char *icq_ConvertStatus2Str(unsigned long status); + +#endif /* _UTIL_H_ */
--- a/src/util.c Tue Nov 28 00:53:27 2000 +0000 +++ b/src/util.c Tue Nov 28 02:22:42 2000 +0000 @@ -828,7 +828,7 @@ return button; } -static GtkTooltips *tips = NULL; +static GtkTooltips *button_tips = NULL; GtkWidget *picture_button2(GtkWidget *window, char *text, char **xpm, short dispstyle) { GtkWidget *button; @@ -838,7 +838,7 @@ GtkWidget *pixmap; GtkWidget *label; - if (!tips) tips = gtk_tooltips_new(); + if (!button_tips) button_tips = gtk_tooltips_new(); button = gtk_button_new(); if (display_options & OPT_DISP_COOL_LOOK) gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); @@ -869,7 +869,7 @@ gtk_box_pack_end(GTK_BOX(button_box_2), label, FALSE, FALSE, 0); } - gtk_tooltips_set_tip(tips, button, text, "Gaim"); + gtk_tooltips_set_tip(button_tips, button, text, "Gaim"); gtk_widget_show(button); return button; }