Mercurial > pidgin.yaz
changeset 2:68b230f8da5f
[gaim-migrate @ 11]
A few more commits :)
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Thu, 23 Mar 2000 03:16:06 +0000 |
parents | 2846a03bda67 |
children | dd6d2c96703a |
files | doc/.cvsignore libfaim/.cvsignore libfaim/BUGS libfaim/CHANGES libfaim/COPYING libfaim/Makefile.am libfaim/README libfaim/aim.h libfaim/aim_auth.c libfaim/aim_buddylist.c libfaim/aim_chat.c libfaim/aim_chatnav.c libfaim/aim_conn.c libfaim/aim_global.c libfaim/aim_im.c libfaim/aim_info.c libfaim/aim_login.c libfaim/aim_logoff.c libfaim/aim_misc.c libfaim/aim_rxhandlers.c libfaim/aim_rxqueue.c libfaim/aim_search.c libfaim/aim_snac.c libfaim/aim_tlv.c libfaim/aim_txqueue.c libfaim/aim_util.c libfaim/faimconfig.h m4/.cvsignore m4/Makefile.am m4/esd.m4 m4/gnome-gnorba-check.m4 m4/gnome-orbit-check.m4 m4/gnome-pthread-check.m4 m4/gnome-x-checks.m4 m4/gnome.m4 pixmaps/.cvsignore src/.cvsignore |
diffstat | 37 files changed, 4716 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/.cvsignore Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,2 @@ +Makefile.in +Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/.cvsignore Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,3 @@ +Makefile +Makefile.in +.deps
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/BUGS Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,29 @@ + +aim.h +----- + - Needs a bit of cleaning + +aim_auth.c +---------- + - Login doesn't take advantage of aim_conn constructs where it could + - Login should allow for multiple BOS connections + +aim_chat.c +---------- + - Needs to be implemented. + +aim_chatnav.c +------------- + - Needs to be implemented. + +aim_conn.c +---------- + - Does not work with proxies. + +aim_search.c +------------ + - Still need aim_usersearch_name() + +aim_snac.c +---------- + - Should implement better SNAC handling
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/CHANGES Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,63 @@ + +No release numbers +------------------ + - Sun Aug 1 03:02:17 UTC 1999 + - Added aimutil_*()s in aim_util.c for raw byte placement + - Cleaned up aim_im.c, aim_auth.c, and aim_login.c using aimutil_* + - Added AIM_IMFLAGS, flags option to aim_send_im(), removed + aim_send_im_away() + - Added client_info parameter to aim_send_login() + - Tweaked aim_send_im() (AOL changed a few things, there's some more + changes left to do) + - Some Chat stuff changed, still no where near functional + - Finally remembered to switch the license to LGPL (from GPL) + - Released a snapshot + + - Sat Jul 31 05:28:38 UTC 1999 + - Changed aim_bos_setdeny() to aim_bos_changevisibility() and actually + did the implementation. + + - Fri Jul 23 17:45:22 UTC 1999 + - Work around for the AOL change in IP syntax (thanks to Eric Peyton) + - Released snapshot + + - Sun Apr 25 23:31:44 UTC 1999 + - Fixed stupid off-by-one bug in aim_logoff() + + - Sun Apr 25 22:43:31 UTC 1999 + - Renamed/reclassified missed IM errors (now all callbacks -- no backend handling) + - Killed aim_login() -- all connections now opened in frontend + - aim_conn_close() will not close fd's < 3 + - Released snapshot. + + - Sat Apr 10 22:44:07 UTC 1999 + - Changed how rx_command->handled works; now uses return value from callback + - Changed the if's in the dispatcher (aim_rxhandlers.c) to switch()es + + - Sat Apr 10 03:51:21 UTC 1999 + - Started CHANGES + - Put in n's aim_snac.c. + - Updated aim_{add,remove}_buddy() to use aim_conn + - Updated aim_usersearch_address() to use aim_conn + - Cleaned up aim.h a bit (removed old *phase* protos) + - Changed gethostbyname() to gethostbyname2() (for MacOS X) + - Changed aim_newconn() to pass connection errors in connstruct->status + - Updated faimtest.c to detect connection errors + - Fixed a small typo in aim_im::aim_parse_incoming_im_middle() + - Added free()s in that function and to userinfo counterpart (fewer leaks) + - Released snapshot + + - Sat Apr 3 06:43:14 UTC 1999 + - Released snapshot + + - Wed Dec 30 01:20:59 MST 1998 + - Released snapshot + + - Mon Dec 7 16:57:57 MST 1998 + - Released snapshot + + - Sat Dec 5 00:01:53 MST 1998 + - Released snapshot + + - Thu Nov 26 17:50:02 MST 1998 + - Released snapshot
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/COPYING Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/Makefile.am Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,14 @@ +noinst_LIBRARIES = $(LIBFAIM_DO) + +EXTRA_LIBRARIES = libfaim.a + +EXTRA_DIST = aim.h faimconfig.h + +libfaim_a_SOURCES = aim_chatnav.c aim_info.c aim_rxhandlers.c \ + aim_tlv.c aim_auth.c aim_conn.c aim_login.c \ + aim_rxqueue.c aim_txqueue.c aim_buddylist.c \ + aim_global.c aim_logoff.c aim_search.c aim_util.c \ + aim_chat.c aim_im.c aim_misc.c aim_snac.c + +CFLAGS += $(GAIM_CFLAGS) -I../src +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/README Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,80 @@ + +libfaim pre-0.90 or so +---------------------- + +This is libfaim, the purpose of which is to implement as much as the +AOL AIM/OSCAR protocol as possible (which should be all of it). After +nearly a year of development, its still nowhere close. + +This is not a full client and never will be. libfaim only implements +the routines to implement a client (ie, there's no user interface). + +Status +------ + +I would not recommend using this version of libfaim in any form yet. It's +beta-quality and I know it leaks memory quite badly. It seems fairly +stable, however. YMMV, YAYOR, etc. + + +Building +-------- + +Everything in this libfaim dist should build cleanly on any UNIX(-like) +operating system. Originally developed on Linux+glibc. Past versions +known to work on Linux+libc5, FreeBSD, HP/UX, Solaris, Mac OS X Server, +and others. + +libfaim builds as both libfaim.a and libfaim.so. If your platform for +some reason does not support dynamic libraries (eg, you get errors when +building libfaim.so), you'll have to tweak the makefiles a bit to get +the utils/ directory to build. + +Otherwise, just do a 'make'. I don't believe I use any specific features +GNU make, but if something fails, make sure you have it. And bash too. + + +Accessories +----------- + +In utils/, you'll find a few things extra: + + faimtest: very rudimentary front-end. no user interface, but does + illustrate the basics of logging in and sending/recieving + messages and buddy list notifications. Potential front- + end authors start here. + + aimpasswd: utility to change an AIM password without using a full + client. Note that at the time of this writing, this + didn't work quite right yet. See the top of the code for + latest status. + +License +------- + +libfaim is covered under my copyright under the terms of the Lesser GNU +Public License, as documented in the file COPYING in the top level directory. + + +Documentation +------------- + +Unfortunatly, there is not currently any documentation on the libfaim API. +Use the source and utils/faimtest/faimtest.c as a reference when coding +front-ends. + + +Contact Info +------------ + +The author (Adam Fritzler), can be reached at afritz@iname.com or mid@auk.cx. + +I did have mailing lists available for faim-related discussion, but they +have dwindled and eventually broke and to my knowledge have yet to fix +themselves. + +Front-end information: + http://www.auk.cx/faim/ +Protocol information: + http://www.auk.cx/faim/protocol/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim.h Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,297 @@ +#ifndef __AIM_H__ +#define __AIM_H__ + +#include <faimconfig.h> + +/* some global includes */ +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> + +#define CONNECT_SIG_LEN 10 /* not used anymore, hopefully */ +#define LOGIN_RESP_LEN 512 /* should only be 334b but no segfault for us! */ + + +/* + * Error codes + */ +#define AIM_CONNECT_ERROR -0x1 +#define AIM_SIGNON_TOO_SOON -0x4 +#define AIM_SERVICE_FULL -0x6f + + +struct login_phase1_struct { + char *screen_name; + char *BOSIP; + char *cookie; + char *email; + ushort regstatus; +}; + +extern struct login_phase1_struct aim_logininfo; + +struct client_info_s { + char clientstring[100]; /* arbitrary number */ + int major; + int minor; + int build; + char country[3]; + char lang[3]; +}; + +struct connection_info_struct { + unsigned int local_seq_num_origin; /* our first seq num */ + int local_command_count; + + unsigned int remote_seq_num_origin; /* oscar's first seqnum */ + int remote_command_count; /* command_count + seq_num_origin = cur_seq_num */ + + char *sn; /* our screen name */ + + int fd; /* socket descriptor */ +}; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define AIM_CONN_MAX 5 +/* these could be arbitrary, but its easier to use the actual AIM values */ +#define AIM_CONN_TYPE_AUTH 0x0007 +#define AIM_CONN_TYPE_ADS 0x0005 +#define AIM_CONN_TYPE_BOS 2 +#define AIM_CONN_TYPE_CHAT 0x000e +#define AIM_CONN_TYPE_CHATNAV 0x000d + +#define AIM_CONN_STATUS_READY 0x0001 +#define AIM_CONN_STATUS_INTERNALERR 0x0002 +#define AIM_CONN_STATUS_RESOLVERR 0x80 +#define AIM_CONN_STATUS_CONNERR 0x40 + + +struct aim_conn_t { + int fd; + int type; + int seqnum; + int status; +}; +struct aim_conn_t aim_conns[AIM_CONN_MAX]; + + +/* struct for incoming commands */ +struct command_rx_struct { + /* byte 1 assumed to always be 0x2a */ + char type; /* type code (byte 2) */ + unsigned int seqnum; /* sequence number (bytes 3 and 4) */ + unsigned int commandlen; /* total packet len - 6 (bytes 5 and 6) */ + char *data; /* packet data (from 7 byte on) */ + unsigned int lock; /* 1 = locked, 0 = open */ + unsigned int handled; /* 1 = been handled, 0 = new */ + struct aim_conn_t *conn; /* the connection it came in on... */ + struct command_rx_struct *next; /* ptr to next struct in list */ +}; + +/* struct for outgoing commands */ +struct command_tx_struct { + /* byte 1 assumed to be 0x2a */ + char type; /* type/family code */ + unsigned int seqnum; /* seqnum dynamically assigned on tx */ + unsigned int commandlen; /* SNAC length */ + char *data; /* packet data */ + unsigned int lock; /* 1 = locked, 0 = open */ + unsigned int sent; /* 1 = has been sent, 0 = new */ + struct aim_conn_t *conn; + struct command_tx_struct *next; /* ptr to next struct in list */ +}; + +/* TLV-related tidbits */ +struct aim_tlv_t { + u_short type; + u_short length; + u_char *value; +}; + +struct aim_tlv_t *aim_grabtlv(u_char *src); +struct aim_tlv_t *aim_grabtlvstr(u_char *src); +int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv); +struct aim_tlv_t *aim_createtlv(void); +int aim_freetlv(struct aim_tlv_t **oldtlv); +int aim_puttlv_16(u_char *, u_short, u_short); + +/* some prototypes... */ + +/* implicitly or explicitly called */ +int aim_get_command(void); +int aim_rxdispatch(void); +int aim_logoff(void); + +typedef int (*rxcallback_t)(struct command_rx_struct *, ...); +int aim_register_callbacks(rxcallback_t *); + +u_long aim_genericreq_n(struct aim_conn_t *conn, u_short family, u_short subtype); +u_long aim_genericreq_l(struct aim_conn_t *conn, u_short family, u_short subtype, u_long *); +u_long aim_genericreq_s(struct aim_conn_t *conn, u_short family, u_short subtype, u_short *); + +/* aim_login.c */ +int aim_send_login (struct aim_conn_t *, char *, char *, struct client_info_s *); +int aim_encode_password(const char *, char *); + + +struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue); + + +int aim_parse_unknown(struct command_rx_struct *command, ...); +int aim_parse_missed_im(struct command_rx_struct *, ...); +int aim_parse_last_bad(struct command_rx_struct *, ...); + +int aim_tx_enqueue(struct command_tx_struct *); +unsigned int aim_get_next_txseqnum(struct aim_conn_t *); +int aim_tx_flushqueue(void); +int aim_tx_printqueue(void); +int aim_tx_purgequeue(void); + +/* queue (linked list) pointers */ +extern struct command_tx_struct *aim_queue_outgoing; /* incoming commands */ +extern struct command_rx_struct *aim_queue_incoming; /* outgoing commands */ + +/* The default callback handler array */ +extern rxcallback_t aim_callbacks[]; + +extern struct aim_snac_t *aim_outstanding_snacs; +extern u_long aim_snac_nextid; + +#define AIM_CB_INCOMING_IM 0 +#define AIM_CB_ONCOMING_BUDDY 1 +#define AIM_CB_OFFGOING_BUDDY 2 +#define AIM_CB_MISSED_IM 3 +#define AIM_CB_MISSED_CALL 4 +#define AIM_CB_LOGIN_P4_C1 5 +#define AIM_CB_LOGIN_P4_C2 6 +#define AIM_CB_LOGIN_P2_1 7 +#define AIM_CB_LOGIN_P2_2 8 +#define AIM_CB_LOGIN_P3_B 9 +#define AIM_CB_LOGIN_P3D_A 10 +#define AIM_CB_LOGIN_P3D_B 11 +#define AIM_CB_LOGIN_P3D_C 12 +#define AIM_CB_LOGIN_P3D_D 13 +#define AIM_CB_LOGIN_P3D_E 14 +#define AIM_CB_LOGIN_P3D_F 15 +#define AIM_CB_RATECHANGE 16 +#define AIM_CB_USERERROR 17 +#define AIM_CB_UNKNOWN 18 +#define AIM_CB_USERINFO 19 +#define AIM_CB_SEARCH_ADDRESS 20 +#define AIM_CB_SEARCH_NAME 21 +#define AIM_CB_SEARCH_FAIL 22 +#define AIM_CB_AUTH_ERROR 23 +#define AIM_CB_AUTH_SUCCESS 24 +#define AIM_CB_AUTH_SVRREADY 25 +#define AIM_CB_AUTH_OTHER 26 +#define AIM_CB_AUTH_INFOCHNG_REPLY 27 +#define AIM_CB_CHATNAV_SVRREADY 28 + +int Read(int, u_char *, int); + +struct aim_snac_t { + u_long id; + u_short family; + u_short type; + u_short flags; + void *data; + time_t issuetime; + struct aim_snac_t *next; +}; +u_long aim_newsnac(struct aim_snac_t *newsnac); +struct aim_snac_t *aim_remsnac(u_long id); +int aim_cleansnacs(int maxage); +int aim_putsnac(u_char *, int, int, int, u_long); + +void aim_connrst(void); +struct aim_conn_t *aim_conn_getnext(void); +void aim_conn_close(struct aim_conn_t *deadconn); +struct aim_conn_t *aim_getconn_type(int type); +struct aim_conn_t *aim_newconn(int type, char *dest); +int aim_conngetmaxfd(void); +struct aim_conn_t *aim_select(struct timeval *); +int aim_conn_isready(struct aim_conn_t *); +int aim_conn_setstatus(struct aim_conn_t *, int); + +/* aim_misc.c */ + +#define AIM_VISIBILITYCHANGE_PERMITADD 0x05 +#define AIM_VISIBILITYCHANGE_PERMITREMOVE 0x06 +#define AIM_VISIBILITYCHANGE_DENYADD 0x07 +#define AIM_VISIBILITYCHANGE_DENYREMOVE 0x08 + +u_long aim_bos_setidle(struct aim_conn_t *, u_long); +u_long aim_bos_changevisibility(struct aim_conn_t *, int, char *); +u_long aim_bos_setbuddylist(struct aim_conn_t *, char *); +u_long aim_bos_setprofile(struct aim_conn_t *, char *); +u_long aim_bos_setgroupperm(struct aim_conn_t *, u_long); +u_long aim_bos_clientready(struct aim_conn_t *); +u_long aim_bos_reqrate(struct aim_conn_t *); +u_long aim_bos_ackrateresp(struct aim_conn_t *); +u_long aim_bos_setprivacyflags(struct aim_conn_t *, u_long); +u_long aim_bos_reqpersonalinfo(struct aim_conn_t *); +u_long aim_bos_reqservice(struct aim_conn_t *, u_short); +u_long aim_bos_reqrights(struct aim_conn_t *); +u_long aim_bos_reqbuddyrights(struct aim_conn_t *); +u_long aim_bos_reqlocaterights(struct aim_conn_t *); +u_long aim_bos_reqicbmparaminfo(struct aim_conn_t *); + +/* aim_rxhandlers.c */ +int aim_register_callbacks(rxcallback_t *); +int aim_rxdispatch(void); +int aim_authparse(struct command_rx_struct *); +int aim_handleredirect_middle(struct command_rx_struct *, ...); +int aim_parse_unknown(struct command_rx_struct *, ...); +int aim_parse_missed_im(struct command_rx_struct *, ...); +int aim_parse_last_bad(struct command_rx_struct *, ...); +int aim_parse_generalerrs(struct command_rx_struct *command, ...); + +/* aim_im.c */ +#define AIM_IMFLAGS_AWAY 0x01 /* mark as an autoreply */ +#define AIM_IMFLAGS_ACK 0x02 /* request a receipt notice */ +u_long aim_send_im(struct aim_conn_t *, char *, int, char *); +int aim_parse_incoming_im_middle(struct command_rx_struct *); + +/* aim_info.c */ +u_long aim_getinfo(struct aim_conn_t *, const char *); +int aim_parse_userinfo_middle(struct command_rx_struct *); + +/* aim_auth.c */ +int aim_auth_sendcookie(struct aim_conn_t *, char *); +u_long aim_auth_clientready(struct aim_conn_t *); +u_long aim_auth_changepasswd(struct aim_conn_t *, char *, char *); + +/* aim_buddylist.c */ +u_long aim_add_buddy(struct aim_conn_t *, char *); +u_long aim_remove_buddy(struct aim_conn_t *, char *); + +/* aim_search.c */ +u_long aim_usersearch_address(struct aim_conn_t *, char *); +/* u_long aim_usersearch_name(struct aim_conn_t *, char *); */ + +/* aim_util.c */ +int aimutil_put8(u_char *, u_short); +int aimutil_put16(u_char *, u_short); +int aimutil_put32(u_char *, u_long); +int aimutil_putstr(u_char *, u_char *, int); + +/* proxy support */ +#ifdef ENABLE_PROXY_SUPPORT +#include "proxy.h" +#endif + +#endif /* __AIM_H__ */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_auth.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,149 @@ +/* + aim_auth.c + + Deals with the authorizer. + + */ + +#include "aim.h" + +/* this just pushes the passed cookie onto the passed connection -- NO SNAC! */ +int aim_auth_sendcookie(struct aim_conn_t *conn, char *chipsahoy) +{ + struct command_tx_struct newpacket; + int curbyte=0; + + newpacket.lock = 1; + + if (conn==NULL) + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH); + else + newpacket.conn = conn; + + newpacket.type = 0x0001; /* channel 1 (no SNACs, you know) */ + + newpacket.commandlen = 4 + 2 + 2 + 0x100; + newpacket.data = (char *) calloc(1, newpacket.commandlen); + + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0006); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0100); + memcpy(&(newpacket.data[curbyte]), chipsahoy, 0x100); + + aim_tx_enqueue(&newpacket); + + return 0; +} + +u_long aim_auth_clientready(struct aim_conn_t *conn) +{ + struct command_tx_struct newpacket; + int curbyte = 0; + + newpacket.lock = 1; + + if (conn==NULL) + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH); + else + newpacket.conn = conn; + + newpacket.type = 0x0002; + + newpacket.commandlen = 26; + newpacket.data = (char *) malloc(newpacket.commandlen); + + curbyte += aim_putsnac(newpacket.data+curbyte, 0x0001, 0x0002, 0x0000, aim_snac_nextid); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0013); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0007); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + + aim_tx_enqueue(&newpacket); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0001; + snac.type = 0x0004; + snac.flags = 0x0000; + + snac.data = NULL; + + aim_newsnac(&snac); + } + + return (aim_snac_nextid++); +} + +u_long aim_auth_changepasswd(struct aim_conn_t *conn, char *new, char *current) +{ + struct command_tx_struct newpacket; + int i; + + newpacket.lock = 1; + + if (conn==NULL) + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH); + else + newpacket.conn = conn; + + newpacket.type = 0x0002; + + newpacket.commandlen = 10 + 4 + strlen(current) + 4 + strlen(new); + newpacket.data = (char *) malloc(newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x07; + + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x04; + + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* current password TLV t(0002) */ + i = 10; + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x02; + newpacket.data[i++] = 0x00; + newpacket.data[i++] = strlen(current) & 0xff; + memcpy(&(newpacket.data[i]), current, strlen(current)); + i += strlen(current); + + /* new password TLV t(0012) */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x12; + newpacket.data[i++] = 0x00; + newpacket.data[i++] = strlen(new) & 0xff; + memcpy(&(newpacket.data[i]), new, strlen(new)); + i+=strlen(new); + + aim_tx_enqueue(&newpacket); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0001; + snac.type = 0x0004; + snac.flags = 0x0000; + + snac.data = NULL; + + aim_newsnac(&snac); + } + + return (aim_snac_nextid++); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_buddylist.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,117 @@ + +#include <aim.h> + +/* + * aim_add_buddy() + * + * Adds a single buddy to your buddy list after login. + * + */ +u_long aim_add_buddy(struct aim_conn_t *conn, char *sn ) +{ + struct command_tx_struct newpacket; + + if( !sn ) + return -1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.lock = 1; + newpacket.type = 0x0002; + newpacket.commandlen = 11 + strlen( sn ); + newpacket.data = (char *)malloc( newpacket.commandlen ); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x03; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x04; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* length of screenname */ + newpacket.data[10] = strlen( sn ); + + memcpy( &(newpacket.data[11]), sn, strlen( sn ) ); + + aim_tx_enqueue( &newpacket ); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0003; + snac.type = 0x0004; + snac.flags = 0x0000; + + snac.data = malloc( strlen( sn ) + 1 ); + memcpy( snac.data, sn, strlen( sn ) + 1 ); + + aim_newsnac( &snac ); + } + + return( aim_snac_nextid++ ); +} + +u_long aim_remove_buddy(struct aim_conn_t *conn, char *sn ) +{ + struct command_tx_struct newpacket; + + if( !sn ) + return -1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.lock = 1; + newpacket.type = 0x0002; + newpacket.commandlen = 11 + strlen(sn); + newpacket.data = (char *)malloc( newpacket.commandlen ); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x03; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x05; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* length of screenname */ + newpacket.data[10] = strlen( sn ); + + memcpy( &(newpacket.data[11]), sn, strlen( sn ) ); + + aim_tx_enqueue( &newpacket ); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0003; + snac.type = 0x0005; + snac.flags = 0x0000; + + snac.data = malloc( strlen( sn ) + 1 ); + memcpy( snac.data, sn, strlen( sn ) + 1 ); + + aim_newsnac( &snac ); + } + + return( aim_snac_nextid++ ); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_chat.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,80 @@ +/* + * aim_chat.c + * + * Routines for the Chat service. Nothing works (yet). + * + */ + +#include "aim.h" + +/* + * FIXME: Doesn't work. + * + */ +u_long aim_chat_join(struct aim_conn_t *conn, const char *roomname) +{ + struct command_tx_struct newpacket; + + newpacket.lock = 1; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x0002; + + newpacket.commandlen = 12+7+strlen(roomname)+6; + newpacket.data = (char *) malloc(newpacket.commandlen); + memset(newpacket.data, 0x00, newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x01; + + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x04; + + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + newpacket.data[10] = 0x00; + newpacket.data[11] = 0x0e; + newpacket.data[12] = 0x00; + newpacket.data[13] = 0x01; + newpacket.data[14] = 0x00; + newpacket.data[15] = 0x0c; + newpacket.data[16] = 0x00; + newpacket.data[17] = 0x04; + newpacket.data[18] = strlen(roomname) & 0x00ff; + memcpy(&(newpacket.data[19]), roomname, strlen(roomname)); + + { + int i = 0; + printf("\n\n\n"); + for (i = 0;i < newpacket.commandlen; i++) + printf("0x%02x ", newpacket.data[i]); + printf("\n\n\n"); + } + + aim_tx_enqueue(&newpacket); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0001; + snac.type = 0x0004; + snac.flags = 0x0000; + + snac.data = malloc(strlen(roomname)); + memcpy(snac.data, roomname, strlen(roomname)); + + aim_newsnac(&snac); + } + + return (aim_snac_nextid++); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_chatnav.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,9 @@ +/* + * + * + * + * + */ + +#include "aim.h" +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_conn.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,195 @@ + +/* + * aim_conn.c + * + * Does all this gloriously nifty connection handling stuff... + * + */ + +#include "aim.h" + +void aim_connrst(void) +{ + int i; + for (i = 0; i < AIM_CONN_MAX; i++) + { + aim_conns[i].fd = -1; + aim_conns[i].type = -1; + aim_conns[i].status = 0; + } + +} + +struct aim_conn_t *aim_conn_getnext(void) +{ + int i; + for (i=0;i<AIM_CONN_MAX;i++) + if (aim_conns[i].fd == -1) + return &(aim_conns[i]); + return NULL; +} + +void aim_conn_close(struct aim_conn_t *deadconn) +{ + if (deadconn->fd >= 3) + close(deadconn->fd); + deadconn->fd = -1; + deadconn->type = -1; +} + +struct aim_conn_t *aim_getconn_type(int type) +{ + int i; + for (i=0; i<AIM_CONN_MAX; i++) + if (aim_conns[i].type == type) + return &(aim_conns[i]); + return NULL; +} + +/* + * aim_newconn(type, dest) + * + * Opens a new connection to the specified dest host of type type. + * + * TODO: fix for proxies + * FIXME: Return errors in a more sane way. + * + */ +struct aim_conn_t *aim_newconn(int type, char *dest) +{ + struct aim_conn_t *connstruct; + int ret; + struct sockaddr_in sa; + struct hostent *hp; + int port = FAIM_LOGIN_PORT; + int i=0; + + if (!dest || ((connstruct=aim_conn_getnext())==NULL)) + return NULL; + + connstruct->type = type; + + /* + * As of 23 Jul 1999, AOL now sends the port number, preceded by a + * colon, in the BOS redirect. This fatally breaks all previous + * libfaims. Bad, bad AOL. + * + * We put this here to catch every case. + * + */ + for(i=0;(i<strlen(dest));i++) + if (dest[i] == ':') break; + if (i<strlen(dest)) + { + port = atoi(dest+i); + dest[i] = '\0'; + } + + hp = gethostbyname2(dest, AF_INET); + if (hp == NULL) + { + connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR); + return connstruct; + } + + memset(&sa.sin_zero, 0, 8); + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); + sa.sin_family = hp->h_addrtype; + + connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0); + ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)); + if( ret < 0) + { + connstruct->fd = -1; + connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); + return connstruct; + } + + return connstruct; +} + +int aim_conngetmaxfd(void) +{ + int i,j; + j=0; + for (i=0;i<AIM_CONN_MAX;i++) + if(aim_conns[i].fd > j) + j = aim_conns[i].fd; + return j; +} + +int aim_countconn(void) +{ + int i,cnt; + cnt = 0; + for (i=0;i<AIM_CONN_MAX;i++) + if (aim_conns[i].fd > -1) + cnt++; + return cnt; +} + +/* + * aim_select(timeout) + * + * Waits for a socket with data or for timeout, whichever comes first. + * See select(2). + * + */ +struct aim_conn_t *aim_select(struct timeval *timeout) +{ + fd_set fds; + fd_set errfds; + int i; + + if (aim_countconn() <= 0) + return 0; + + FD_ZERO(&fds); + FD_ZERO(&errfds); + + for(i=0;i<AIM_CONN_MAX;i++) + if (aim_conns[i].fd>-1) + { + FD_SET(aim_conns[i].fd, &fds); + FD_SET(aim_conns[i].fd, &errfds); + } + + i = select(aim_conngetmaxfd()+1, &fds, NULL, &errfds, timeout); + if (i>=1) + { + int j; + for (j=0;j<AIM_CONN_MAX;j++) + { + if ((FD_ISSET(aim_conns[j].fd, &errfds))) + { + /* got an exception; close whats left of it up */ + aim_conn_close(&(aim_conns[j])); + return (struct aim_conn_t *)-1; + } + else if ((FD_ISSET(aim_conns[j].fd, &fds))) + return &(aim_conns[j]); /* return the first waiting struct */ + } + /* should never get here */ + } + else + return (struct aim_conn_t *)i; /* no waiting or error, return -- FIXME: return type funnies */ + return NULL; /* NO REACH */ +} + +int aim_conn_isready(struct aim_conn_t *conn) +{ + if (conn) + return (conn->status & 0x0001); + else + return -1; +} + +int aim_conn_setstatus(struct aim_conn_t *conn, int status) +{ + if (conn) + return (conn->status ^= status); + else + return -1; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_global.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,17 @@ +/* + aim_global.c + + These are things that are globally required, but don't fit the + naming of the rest of the functions. Namely, the queue ptrs and fds. + + */ + +#include "aim.h" + +/* the dreaded global variables... */ + +struct login_phase1_struct aim_logininfo; + +/* queue (linked list) pointers */ +struct command_tx_struct *aim_queue_outgoing = NULL; /* incoming commands */ +struct command_rx_struct *aim_queue_incoming = NULL; /* outgoing commands */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_im.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,253 @@ +/* + * aim_im.c + * + * The routines for sending/receiving Instant Messages. + * + */ + +#include "aim.h" + +/* + * Send an ICBM (instant message). + * + * + * Possible flags: + * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse + * AIM_IMFLAGS_ACK -- Requests that the server send an ack + * when the message is received (of type 0x0004/0x000c) + * + * + * TODO: Update to new standard form + * + * + */ + +u_long aim_send_im(struct aim_conn_t *conn, char *destsn, int flags, char *msg) +{ + + int curbyte; + struct command_tx_struct newpacket; + + newpacket.lock = 1; /* lock struct */ + newpacket.type = 0x02; /* IMs are always family 0x02 */ + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.commandlen = 20+1+strlen(destsn)+1+1+2+7+2+4+strlen(msg)+2; + + if (flags & AIM_IMFLAGS_ACK) + newpacket.commandlen += 4; + if (flags & AIM_IMFLAGS_AWAY) + newpacket.commandlen += 4; + + newpacket.data = (char *) calloc(1, newpacket.commandlen); + + curbyte = 0; + curbyte += aim_putsnac(newpacket.data+curbyte, 0x0004, 0x0006, 0x0000, aim_snac_nextid); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); + curbyte += aimutil_put8(newpacket.data+curbyte,strlen(destsn)); + curbyte += aimutil_putstr(newpacket.data+curbyte, destsn, strlen(destsn)); + + if (flags & AIM_IMFLAGS_ACK) + { + curbyte += aimutil_put16(newpacket.data+curbyte,0x0003); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + } + + if (flags & AIM_IMFLAGS_AWAY) + { + curbyte += aimutil_put16(newpacket.data+curbyte,0x0004); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + } + + curbyte += aimutil_put16(newpacket.data+curbyte,0x0002); + curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+0xf); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0501); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); + curbyte += aimutil_put8(newpacket.data+curbyte,0x01); + curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+4); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); + curbyte += aimutil_putstr(newpacket.data+curbyte, msg, strlen(msg)); + + aim_tx_enqueue(&newpacket); + +#ifdef USE_SNAC_FOR_IMS + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0004; + snac.type = 0x0006; + snac.flags = 0x0000; + + snac.data = malloc(strlen(destsn)+1); + memcpy(snac.data, destsn, strlen(destsn)+1); + + aim_newsnac(&snac); + } + + aim_cleansnacs(60); /* clean out all SNACs over 60sec old */ +#endif + + return (aim_snac_nextid++); +} + +int aim_parse_incoming_im_middle(struct command_rx_struct *command) +{ + int i = 0; + char *srcsn = NULL; + char *msg = NULL; + unsigned int msglen = 0; + int warninglevel = 0; + int tlvcnt = 0; + int class = 0; + ulong membersince = 0; + ulong onsince = 0; + int idletime = 0; + int isautoreply = 0; + + i = 20; + + srcsn = malloc(command->data[i] + 1); + memcpy(srcsn, &(command->data[i+1]), command->data[i]); + srcsn[(int)command->data[i]] = '\0'; + + i += (int) command->data[i] + 1; /* add SN len */ + + /* warning level */ + warninglevel = (command->data[i] << 8); + warninglevel += (command->data[i+1]); + i += 2; + + tlvcnt = ((command->data[i++]) << 8) & 0xFF00; + tlvcnt += (command->data[i++]) & 0x00FF; + + /* a mini TLV parser */ + { + int curtlv = 0; + int tlv1 = 0; + + while (curtlv < tlvcnt) + { + if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x01) ) + { + if (tlv1) + break; + /* t(0001) = class */ + if (command->data[i+3] != 0x02) + printf("faim: userinfo: **warning: strange v(%x) for t(1)\n", command->data[i+3]); + class = ((command->data[i+4]) << 8) & 0xFF00; + class += (command->data[i+5]) & 0x00FF; + i += (2 + 2 + command->data[i+3]); + tlv1++; + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x02)) + { + /* t(0002) = member since date */ + if (command->data[i+3] != 0x04) + printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]); + + membersince = ((command->data[i+4]) << 24) & 0xFF000000; + membersince += ((command->data[i+5]) << 16) & 0x00FF0000; + membersince += ((command->data[i+6]) << 8) & 0x0000FF00; + membersince += ((command->data[i+7]) ) & 0x000000FF; + i += (2 + 2 + command->data[i+3]); + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x03)) + { + /* t(0003) = on since date */ + if (command->data[i+3] != 0x04) + printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]); + + onsince = ((command->data[i+4]) << 24) & 0xFF000000; + onsince += ((command->data[i+5]) << 16) & 0x00FF0000; + onsince += ((command->data[i+6]) << 8) & 0x0000FF00; + onsince += ((command->data[i+7]) ) & 0x000000FF; + i += (2 + 2 + command->data[i+3]); + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x04) ) + { + /* t(0004) = idle time */ + if (command->data[i+3] != 0x02) + printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]); + idletime = ((command->data[i+4]) << 8) & 0xFF00; + idletime += (command->data[i+5]) & 0x00FF; + i += (2 + 2 + command->data[i+3]); + } + else + { + printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]); + i += (2 + 2 + command->data[i+3]); + } + curtlv++; + } + } + + { + /* detect if this is an auto-response or not */ + /* auto-responses can be detected by the presence of a *second* TLV with + t(0004), but of zero length (and therefore no value portion) */ + struct aim_tlv_t *tsttlv = NULL; + tsttlv = aim_grabtlv((u_char *) &(command->data[i])); + if (tsttlv->type == 0x04) + isautoreply = 1; + aim_freetlv(&tsttlv); + } + + i += 2; + + i += 2; /* skip first msglen */ + i += 7; /* skip garbage */ + i -= 4; + + /* oh boy is this terrible... this comes from a specific of the spec */ + while(1) + { + if ( ( (command->data[i] == 0x00) && + (command->data[i+1] == 0x00) && + (command->data[i+2] == 0x00) && + (command->data[i+3] == 0x00) ) && + (i < command->commandlen) ) /* prevent infinity */ + break; + else + i++; + } + + i -= 2; + + if ( (command->data[i] == 0x00) && + (command->data[i+1] == 0x00) ) + i += 2; + + msglen = ( (( (unsigned int) command->data[i]) & 0xFF ) << 8); + msglen += ( (unsigned int) command->data[i+1]) & 0xFF; /* mask off garbage */ + i += 2; + + msglen -= 4; /* skip four 0x00s */ + i += 4; + + msg = malloc(msglen +1); + + memcpy(msg, &(command->data[i]), msglen); + msg[msglen] = '\0'; + + i = (aim_callbacks[AIM_CB_INCOMING_IM])(command, srcsn, msg, warninglevel, class, membersince, onsince, idletime, isautoreply); + + free(srcsn); + free(msg); + + return i; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_info.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,220 @@ +/* + aim_info.c + + The functions here are responsible for requesting and parsing information- + gathering SNACs. + + */ + + +#include "aim.h" /* for most everything */ + +u_long aim_getinfo(struct aim_conn_t *conn, const char *sn) +{ + struct command_tx_struct newpacket; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.lock = 1; + newpacket.type = 0x0002; + + newpacket.commandlen = 12 + 1 + strlen(sn); + newpacket.data = (char *) malloc(newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x02; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x05; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* TLV: Screen Name */ + /* t(0x0001) */ + newpacket.data[10] = 0x00; + newpacket.data[11] = 0x01; + /* l() */ + newpacket.data[12] = strlen(sn); + /* v() */ + memcpy(&(newpacket.data[13]), sn, strlen(sn)); + + aim_tx_enqueue(&newpacket); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x0002; + snac.type = 0x0005; + snac.flags = 0x0000; + + snac.data = malloc(strlen(sn)+1); + memcpy(snac.data, sn, strlen(sn)+1); + + aim_newsnac(&snac); + } + + return (aim_snac_nextid++); +} + +/* + * This parses the user info stuff out all nice and pretty then calls + * the higher-level callback (in the user app). + * + */ + +int aim_parse_userinfo_middle(struct command_rx_struct *command) +{ + char *sn = NULL; + char *prof_encoding = NULL; + char *prof = NULL; + u_short warnlevel = 0x0000; + u_short idletime = 0x0000; + u_short class = 0x0000; + u_long membersince = 0x00000000; + u_long onlinesince = 0x00000000; + int tlvcnt = 0; + int i = 0; + + { + u_long snacid = 0x000000000; + struct aim_snac_t *snac = NULL; + + snacid = (command->data[6] << 24) & 0xFF000000; + snacid+= (command->data[7] << 16) & 0x00FF0000; + snacid+= (command->data[8] << 8) & 0x0000FF00; + snacid+= (command->data[9]) & 0x000000FF; + + snac = aim_remsnac(snacid); + + free(snac->data); + free(snac); + + } + + sn = (char *) malloc(command->data[10]+1); + memcpy(sn, &(command->data[11]), command->data[10]); + sn[(int)command->data[10]] = '\0'; + + i = 11 + command->data[10]; + warnlevel = ((command->data[i++]) << 8) & 0xFF00; + warnlevel += (command->data[i++]) & 0x00FF; + + tlvcnt = ((command->data[i++]) << 8) & 0xFF00; + tlvcnt += (command->data[i++]) & 0x00FF; + + /* a mini TLV parser */ + { + int curtlv = 0; + int tlv1 = 0; + + while (curtlv < tlvcnt) + { + if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x01) ) + { + if (tlv1) + break; + /* t(0001) = class */ + class = ((command->data[i+4]) << 8) & 0xFF00; + class += (command->data[i+5]) & 0x00FF; + i += (2 + 2 + command->data[i+3]); + tlv1++; + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x02)) + { + /* t(0002) = member since date */ + if (command->data[i+3] != 0x04) + printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]); + + membersince = ((command->data[i+4]) << 24) & 0xFF000000; + membersince += ((command->data[i+5]) << 16) & 0x00FF0000; + membersince += ((command->data[i+6]) << 8) & 0x0000FF00; + membersince += ((command->data[i+7]) ) & 0x000000FF; + i += (2 + 2 + command->data[i+3]); + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x03)) + { + /* t(0003) = on since date */ + if (command->data[i+3] != 0x04) + printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]); + + onlinesince = ((command->data[i+4]) << 24) & 0xFF000000; + onlinesince += ((command->data[i+5]) << 16) & 0x00FF0000; + onlinesince += ((command->data[i+6]) << 8) & 0x0000FF00; + onlinesince += ((command->data[i+7]) ) & 0x000000FF; + i += (2 + 2 + command->data[i+3]); + } + else if ((command->data[i] == 0x00) && + (command->data[i+1] == 0x04) ) + { + /* t(0004) = idle time */ + if (command->data[i+3] != 0x02) + printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]); + idletime = ((command->data[i+4]) << 8) & 0xFF00; + idletime += (command->data[i+5]) & 0x00FF; + i += (2 + 2 + command->data[i+3]); + } + else + { + printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]); + i += (2 + 2 + command->data[i+3]); + } + curtlv++; + } + } + if (i < command->commandlen) + { + if ( (command->data[i] == 0x00) && + (command->data[i+1] == 0x01) ) + { + int len = 0; + + len = ((command->data[i+2] << 8) & 0xFF00); + len += (command->data[i+3]) & 0x00FF; + + prof_encoding = (char *) malloc(len+1); + memcpy(prof_encoding, &(command->data[i+4]), len); + prof_encoding[len] = '\0'; + + i += (2+2+len); + } + else + { + printf("faim: userinfo: **warning: unexpected TLV after TLVblock t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]); + i += 2 + 2 + command->data[i+3]; + } + } + + if (i < command->commandlen) + { + int len = 0; + + len = ((command->data[i+2]) << 8) & 0xFF00; + len += (command->data[i+3]) & 0x00FF; + + prof = (char *) malloc(len+1); + memcpy(prof, &(command->data[i+4]), len); + prof[len] = '\0'; + } + else + printf("faim: userinfo: **early parse abort...no profile?\n"); + + i = (aim_callbacks[AIM_CB_USERINFO])(command, sn, prof_encoding, prof, warnlevel, idletime, class, membersince, onlinesince); + + free(sn); + free(prof_encoding); + free(prof); + + return i; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_login.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,142 @@ +/* + * aim_login.c + * + * This contains all the functions needed to actually login. + * + */ + +#include "aim.h" + + +/* + * FIXME: Reimplement the TIS stuff. + */ +#ifdef TIS_TELNET_PROXY +#include "tis_telnet_proxy.h" +#endif + +/* + * send_login(int socket, char *sn, char *password) + * + * This is the initial login request packet. + * + * The password is encoded before transmition, as per + * encode_password(). See that function for their + * stupid method of doing it. + * + * + * + */ +int aim_send_login (struct aim_conn_t *conn, char *sn, char *password, struct client_info_s *clientinfo) +{ + char *password_encoded = NULL; /* to store encoded password */ + int curbyte=0; + + struct command_tx_struct newpacket; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_AUTH); + + newpacket.commandlen = 6+2+strlen(sn)+1+1+2+strlen(password)+6; + + if (clientinfo) + { + if (strlen(clientinfo->clientstring)) + newpacket.commandlen += strlen(clientinfo->clientstring)+4; + newpacket.commandlen += 6+6+6; + if (strlen(clientinfo->country)) + newpacket.commandlen += strlen(clientinfo->country)+4; + if (strlen(clientinfo->lang)) + newpacket.commandlen += strlen(clientinfo->lang)+4; + } + + newpacket.data = (char *) calloc (1, newpacket.commandlen ); + newpacket.lock = 1; + newpacket.type = 0x01; + + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0000); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0001); + curbyte += aimutil_put16(newpacket.data+curbyte, strlen(sn)); + curbyte += aimutil_putstr(newpacket.data+curbyte, sn, strlen(sn)); + + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0002); + curbyte += aimutil_put16(newpacket.data+curbyte, strlen(password)); + password_encoded = (char *) malloc(strlen(password)); + aim_encode_password(password, password_encoded); + curbyte += aimutil_putstr(newpacket.data+curbyte, password_encoded, strlen(password)); + free(password_encoded); + + curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0016, 0x0001); + + if (clientinfo) + { + if (strlen(clientinfo->clientstring)) + { + curbyte += aimutil_put16(newpacket.data+curbyte, 0x0003); + curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->clientstring)); + curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->clientstring, strlen(clientinfo->clientstring)); + } + curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0017, 0x0001); + curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0018, 0x0001); + curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x001a, 0x0013); + if (strlen(clientinfo->country)) + { + curbyte += aimutil_put16(newpacket.data+curbyte, 0x000e); + curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->country)); + curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->country, strlen(clientinfo->country)); + } + if (strlen(clientinfo->lang)) + { + curbyte += aimutil_put16(newpacket.data+curbyte, 0x000f); + curbyte += aimutil_put16(newpacket.data+curbyte, strlen(clientinfo->lang)); + curbyte += aimutil_putstr(newpacket.data+curbyte, clientinfo->lang, strlen(clientinfo->lang)); + } + } + + curbyte += aim_puttlv_16(newpacket.data+curbyte, 0x0009, 0x0015); + + newpacket.lock = 0; + aim_tx_enqueue(&newpacket); + + return 0; +} + +/* + * int encode_password( + * const char *password, + * char *encoded + * ); + * + * This takes a const pointer to a (null terminated) string + * containing the unencoded password. It also gets passed + * an already allocated buffer to store the encoded password. + * This buffer should be the exact length of the password without + * the null. The encoded password buffer IS NOT NULL TERMINATED. + * + * The encoding_table seems to be a fixed set of values. We'll + * hope it doesn't change over time! + * + */ +int aim_encode_password(const char *password, char *encoded) +{ + char encoding_table[] = { + 0xf3, 0xb3, 0x6c, 0x99, + 0x95, 0x3f, 0xac, 0xb6, + 0xc5, 0xfa, 0x6b, 0x63, + 0x69, 0x6c, 0xc3, 0x9f + }; + + int i; + + for (i = 0; i < strlen(password); i++) + encoded[i] = (password[i] ^ encoding_table[i]); + + return 0; +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_logoff.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,28 @@ +/* + * aim_logoff.c + * + * + */ + +#include "aim.h" + +/* + * aim_logoff() + * + * Closes -ALL- open connections. + * + */ +int aim_logoff(void) +{ + int i = AIM_CONN_MAX-1; + while (i > -1) + { + if (aim_conns[i].fd>-1) + aim_conn_close(&(aim_conns[i])); + i--; + } + aim_connrst(); /* in case we want to connect again */ + + return 0; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_misc.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,674 @@ + +/* + * aim_misc.c + * + * TODO: Seperate a lot of this into an aim_bos.c. + * + * Other things... + * + * - Idle setting + * + * + */ + +#include "aim.h" + +/* + * aim_bos_setidle() + * + * Should set your current idle time in seconds. Idealy, OSCAR should + * do this for us. But, it doesn't. The client must call this to set idle + * time. + * + */ +u_long aim_bos_setidle(struct aim_conn_t *conn, u_long idletime) +{ + return aim_genericreq_l(conn, 0x0001, 0x0011, &idletime); +} + + +/* + * aim_bos_changevisibility(conn, changtype, namelist) + * + * Changes your visibility depending on changetype: + * + * AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you + * AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list + * AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names + * AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again + * + * list should be a list of + * screen names in the form "Screen Name One&ScreenNameTwo&" etc. + * + * Equivelents to options in WinAIM: + * - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD + * with only your name on it. + * - Allow only users on my Buddy List: Send an + * AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your + * buddy list + * - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD + * with everyone listed that you want to see you. + * - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only + * yourself in the list + * - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with + * the list of users to be blocked + * + * + */ +u_long aim_bos_changevisibility(struct aim_conn_t *conn, int changetype, char *denylist) +{ + struct command_tx_struct newpacket; + + char *localcpy = NULL; + char *tmpptr = NULL; + char *tmpptr2 = NULL; + int i,j; + + if (!denylist) + return 0; + + newpacket.lock = 1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.type = 0x02; + newpacket.commandlen = 10; + + localcpy = (char *) malloc(strlen(denylist)+1); + memcpy(localcpy, denylist, strlen(denylist)+1); + tmpptr2 = localcpy; /* save this for the free() */ + + i = 0; + tmpptr = strsep(&localcpy, "&"); + while (strlen(tmpptr) && (i < 100)) + { + newpacket.commandlen += strlen(tmpptr)+1; + i++; + tmpptr = strsep(&localcpy, "&"); + } + free(tmpptr2); + tmpptr2 = NULL; + + newpacket.data = (char *) malloc(newpacket.commandlen); + memset(newpacket.data, 0x00, newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x09; + newpacket.data[2] = 0x00; + switch(changetype) + { + case AIM_VISIBILITYCHANGE_PERMITADD: + newpacket.data[3] = 0x05; break; + case AIM_VISIBILITYCHANGE_PERMITREMOVE: + newpacket.data[3] = 0x06; break; + case AIM_VISIBILITYCHANGE_DENYADD: + newpacket.data[3] = 0x07; break; + case AIM_VISIBILITYCHANGE_DENYREMOVE: + newpacket.data[4] = 0x08; break; + default: + return 0; + } + /* SNAC reqid -- we actually DO NOT send a SNAC ID with this one! */ + newpacket.data[6] = 0; + newpacket.data[7] = 0; + newpacket.data[8] = 0; + newpacket.data[9] = 0; + + j = 10; /* the next byte */ + + localcpy = (char *) malloc(strlen(denylist)+1); + memcpy(localcpy, denylist, strlen(denylist)+1); + tmpptr2 = localcpy; /* save this for the free() */ + + i = 0; + tmpptr = strsep(&localcpy, "&"); + while (strlen(tmpptr) && (i < 100)) + { + newpacket.data[j] = strlen(tmpptr); + memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr)); + j += strlen(tmpptr)+1; + i++; + tmpptr = strsep(&localcpy, "&"); + } + free(tmpptr2); + + newpacket.lock = 0; + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid); /* dont increment */ + +} + + + +/* + * aim_bos_setbuddylist(buddylist) + * + * This just builds the "set buddy list" command then queues it. + * + * buddy_list = "Screen Name One&ScreenNameTwo&"; + * + * TODO: Clean this up. + * + */ +u_long aim_bos_setbuddylist(struct aim_conn_t *conn, char *buddy_list) +{ + int i, j; + + struct command_tx_struct newpacket; + + int packet_login_phase3c_hi_b_len = 0; + + char *localcpy = NULL; + char *tmpptr = NULL; + + packet_login_phase3c_hi_b_len = 16; /* 16b for FLAP and SNAC headers */ + + /* bail out if we can't make the packet */ + if (buddy_list == NULL) + { + printf("\nNO BUDDIES! ARE YOU THAT LONELY???\n"); + return 0; + } +#if debug > 0 + printf("****buddy list: %s\n", buddy_list); + printf("****buddy list len: %d (%x)\n", strlen(buddy_list), strlen(buddy_list)); +#endif + + localcpy = (char *) malloc(strlen(buddy_list)+1); + memcpy(localcpy, buddy_list, strlen(buddy_list)+1); + + i = 0; + tmpptr = strtok(localcpy, "&"); + while ((tmpptr != NULL) && (i < 100)) + { +#if debug > 0 + printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr)); +#endif + packet_login_phase3c_hi_b_len += strlen(tmpptr)+1; + i++; + tmpptr = strtok(NULL, "&"); + } +#if debug > 0 + printf("*** send buddy list len: %d (%x)\n", packet_login_phase3c_hi_b_len, packet_login_phase3c_hi_b_len); +#endif + free(localcpy); + + newpacket.type = 0x02; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.commandlen = packet_login_phase3c_hi_b_len - 6; + newpacket.lock = 1; + + newpacket.data = (char *) malloc(newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x03; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x04; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + j = 10; /* the next byte */ + + i = 0; + tmpptr = strtok(buddy_list, "&"); + while ((tmpptr != NULL) & (i < 100)) + { +#if debug > 0 + printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr)); +#endif + newpacket.data[j] = strlen(tmpptr); + memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr)); + j += strlen(tmpptr)+1; + i++; + tmpptr = strtok(NULL, "&"); + } + + newpacket.lock = 0; + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid++); +} + +/* + * aim_bos_setprofile(profile) + * + * Gives BOS your profile. + * + */ +u_long aim_bos_setprofile(struct aim_conn_t *conn, char *profile) +{ + int packet_profile_len = 0; + struct command_tx_struct newpacket; + int i = 0; + + /* len: SNAC */ + packet_profile_len = 10; + /* len: T+L (where t(0001)) */ + packet_profile_len += 2 + 2; + /* len: V (where t(0001)) */ + packet_profile_len += strlen("text/x-aolrtf"); + /* len: T+L (where t(0002)) */ + packet_profile_len += 2 + 2; + /* len: V (where t(0002)) */ + packet_profile_len += strlen(profile); + + newpacket.type = 0x02; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.commandlen = packet_profile_len; + newpacket.data = (char *) malloc(packet_profile_len); + + i = 0; + /* SNAC: family */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x02; + /* SNAC: subtype */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x04; + /* SNAC: flags */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x00; + /* SNAC: id */ + /* SNAC reqid */ + newpacket.data[i++] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[i++] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[i++] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[i++] = (aim_snac_nextid) & 0xFF; + /* TLV t(0001) */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x01; + /* TLV l(000d) */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x0d; + /* TLV v(text/x-aolrtf) */ + memcpy(&(newpacket.data[i]), "text/x-aolrtf", 0x000d); + i += 0x000d; + + /* TLV t(0002) */ + newpacket.data[i++] = 0x00; + newpacket.data[i++] = 0x02; + /* TLV l() */ + newpacket.data[i++] = (strlen(profile) >> 8) & 0xFF; + newpacket.data[i++] = (strlen(profile) & 0xFF); + /* TLV v(profile) */ + memcpy(&(newpacket.data[i]), profile, strlen(profile)); + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid++); +} + +/* + * aim_bos_setgroupperm(mask) + * + * Set group permisson mask. Normally 0x1f. + * + */ +u_long aim_bos_setgroupperm(struct aim_conn_t *conn, u_long mask) +{ + return aim_genericreq_l(conn, 0x0009, 0x0004, &mask); +} + +/* + * aim_bos_clientready() + * + * Send Client Ready. + * + * TODO: Dynamisize. + * + */ +u_long aim_bos_clientready(struct aim_conn_t *conn) +{ + char command_2[] = { + 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x7a, 0x8c, + 0x11, 0xab, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x13, 0x00, 0x09, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01 + }; + int command_2_len = 0x52; + struct command_tx_struct newpacket; + + newpacket.lock = 1; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + newpacket.commandlen = command_2_len; + newpacket.data = (char *) malloc (newpacket.commandlen); + memcpy(newpacket.data, command_2, newpacket.commandlen); + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid++); +} + +/* + * send_login_phase3(int socket) + * + * Request Rate Information. + * + * TODO: Move to aim_conn. + * TODO: Move to SNAC interface. + */ +u_long aim_bos_reqrate(struct aim_conn_t *conn) +{ + return aim_genericreq_n(conn, 0x0001, 0x0006); +} + +/* + * send_login_phase3b(int socket) + * + * Rate Information Response Acknowledge. + * + */ +u_long aim_bos_ackrateresp(struct aim_conn_t *conn) +{ + struct command_tx_struct newpacket; + + newpacket.lock = 1; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + newpacket.commandlen = 18; + + newpacket.data = (char *) malloc(newpacket.commandlen); + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x01; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x08; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + newpacket.data[10] = 0x00; + newpacket.data[11] = 0x01; + newpacket.data[12] = 0x00; + newpacket.data[13] = 0x02; + newpacket.data[14] = 0x00; + newpacket.data[15] = 0x03; + newpacket.data[16] = 0x00; + newpacket.data[17] = 0x04; + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid++); +} + +/* + * aim_bos_setprivacyflags() + * + * Sets privacy flags. Normally 0x03. + * + * Bit 1: Allows other AIM users to see how long you've been idle. + * + * + */ +u_long aim_bos_setprivacyflags(struct aim_conn_t *conn, u_long flags) +{ + return aim_genericreq_l(conn, 0x0001, 0x0014, &flags); +} + +/* + * aim_bos_reqpersonalinfo() + * + * Requests the current user's information. Can't go generic on this one + * because aparently it uses SNAC flags. + * + */ +u_long aim_bos_reqpersonalinfo(struct aim_conn_t *conn) +{ + struct command_tx_struct newpacket; + + newpacket.lock = 1; + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + newpacket.commandlen = 12; + + newpacket.data = (char *) malloc(newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x0a; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x01; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x0e; /* huh? */ + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + newpacket.data[10] = 0x0d; + newpacket.data[11] = 0xda; + + aim_tx_enqueue(&newpacket); + + return (aim_snac_nextid++); +} + +/* + * aim_bos_reqservice(serviceid) + * + * Service request. + * + */ +u_long aim_bos_reqservice(struct aim_conn_t *conn, u_short serviceid) +{ + return aim_genericreq_s(conn, 0x0001, 0x0004, &serviceid); +} + +/* + * aim_bos_reqrights() + * + * Request BOS rights. + * + */ +u_long aim_bos_reqrights(struct aim_conn_t *conn) +{ + return aim_genericreq_n(conn, 0x0009, 0x0002); +} + +/* + * aim_bos_reqbuddyrights() + * + * Request Buddy List rights. + * + */ +u_long aim_bos_reqbuddyrights(struct aim_conn_t *conn) +{ + return aim_genericreq_n(conn, 0x0003, 0x0002); +} + +/* + * Generic routine for sending commands. + * + * + * I know I can do this in a smarter way...but I'm not thinking straight + * right now... + * + * I had one big function that handled all three cases, but then it broke + * and I split it up into three. But then I fixed it. I just never went + * back to the single. I don't see any advantage to doing it either way. + * + */ +u_long aim_genericreq_n(struct aim_conn_t *conn, u_short family, u_short subtype) +{ + struct command_tx_struct newpacket; + + newpacket.lock = 1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + + newpacket.commandlen = 10; + + newpacket.data = (char *) malloc(newpacket.commandlen); + memset(newpacket.data, 0x00, newpacket.commandlen); + newpacket.data[0] = (family & 0xff00)>>8; + newpacket.data[1] = family & 0xff; + newpacket.data[2] = (subtype & 0xff00)>>8; + newpacket.data[3] = subtype & 0xff; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + aim_tx_enqueue(&newpacket); + return (aim_snac_nextid++); +} + +/* + * + * + */ +u_long aim_genericreq_l(struct aim_conn_t *conn, u_short family, u_short subtype, u_long *longdata) +{ + struct command_tx_struct newpacket; + u_long newlong; + + /* If we don't have data, there's no reason to use this function */ + if (!longdata) + return aim_genericreq_n(conn, family, subtype); + + newpacket.lock = 1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + + newpacket.commandlen = 10+sizeof(u_long); + + newpacket.data = (char *) malloc(newpacket.commandlen); + memset(newpacket.data, 0x00, newpacket.commandlen); + + newpacket.data[0] = (family & 0xff00)>>8; + newpacket.data[1] = family & 0xff; + newpacket.data[2] = (subtype & 0xff00)>>8; + newpacket.data[3] = subtype & 0xff; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* copy in data */ + newlong = htonl(*longdata); + memcpy(&(newpacket.data[10]), &newlong, sizeof(u_long)); + + aim_tx_enqueue(&newpacket); + return (aim_snac_nextid++); +} + +u_long aim_genericreq_s(struct aim_conn_t *conn, u_short family, u_short subtype, u_short *shortdata) +{ + struct command_tx_struct newpacket; + u_short newshort; + + /* If we don't have data, there's no reason to use this function */ + if (!shortdata) + return aim_genericreq_n(conn, family, subtype); + + newpacket.lock = 1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + newpacket.type = 0x02; + + newpacket.commandlen = 10+sizeof(u_short); + + newpacket.data = (char *) malloc(newpacket.commandlen); + memset(newpacket.data, 0x00, newpacket.commandlen); + + newpacket.data[0] = (family & 0xff00)>>8; + newpacket.data[1] = family & 0xff; + newpacket.data[2] = (subtype & 0xff00)>>8; + newpacket.data[3] = subtype & 0xff; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + /* copy in data */ + newshort = htons(*shortdata); + memcpy(&(newpacket.data[10]), &newshort, sizeof(u_short)); + + aim_tx_enqueue(&newpacket); + return (aim_snac_nextid++); +} + +/* + * aim_bos_reqlocaterights() + * + * Request Location services rights. + * + */ +u_long aim_bos_reqlocaterights(struct aim_conn_t *conn) +{ + return aim_genericreq_n(conn, 0x0002, 0x0002); +} + +/* + * aim_bos_reqicbmparaminfo() + * + * Request ICBM parameter information. + * + */ +u_long aim_bos_reqicbmparaminfo(struct aim_conn_t *conn) +{ + return aim_genericreq_n(conn, 0x0004, 0x0004); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_rxhandlers.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,485 @@ + +/* + aim_rxhandlers.c + + This file contains most all of the incoming packet handlers, along + with aim_rxdispatch(), the Rx dispatcher. Queue/list management is + actually done in aim_rxqueue.c. + + */ + + +#include "aim.h" /* for most everything */ + +int bleck(struct command_rx_struct *param, ...) +{ + return 1; +} + +/* + * The callbacks. Used to pass data up from the wire into the client. + * + * TODO: MASSIVE OVERHAUL. This method of doing it (array of function + * pointers) is ugly. Overhaul may mean including chained callbacks + * for having client features such as run-time loadable modules. + * + */ +rxcallback_t aim_callbacks[] = { + bleck, /* incoming IM */ + bleck, /* oncoming buddy */ + bleck, /* offgoing buddy */ + bleck, /* messaging error */ + bleck, /* server missed call */ + bleck, /* login phase 4 packet C command 1*/ + bleck, /* login phase 4 packet C command 2 */ + bleck, /* login phase 2, first resp */ + bleck, /* login phase 2, second resp -- **REQUIRED** */ + bleck, /* login phase 3 packet B */ + bleck, /* login phase 3D packet A */ + bleck, /* login phase 3D packet B */ + bleck, /* login phase 3D packet C */ + bleck, /* login phase 3D packet D */ + bleck, /* login phase 3D packet E */ + bleck, /* redirect -- **REQUIRED** */ + bleck, /* server rate change */ + bleck, /* user location error */ + aim_parse_unknown, /* completely unknown command */ + bleck, /* User Info Response */ + bleck, /* User Search by Address response */ + bleck, /* User Search by Name response */ + bleck, /* user search fail */ + bleck, /* auth error */ + bleck, /* auth success */ + bleck, /* auth server ready */ + bleck, /* auth other */ + bleck, /* info change reply */ + bleck, /* ChatNAV: server ready */ + 0x00 +}; + + +int aim_register_callbacks(rxcallback_t *newcallbacks) +{ + int i = 0; + + for (i = 0; aim_callbacks[i] != 0x00; i++) + { + if ( (newcallbacks[i] != NULL) && + (newcallbacks[i] != 0x00) ) + { +#if debug > 3 + printf("aim_register_callbacks: changed handler %d\n", i); +#endif + aim_callbacks[i] = newcallbacks[i]; + } + } + + return 0; +} + +/* + aim_rxdispatch() + + Basically, heres what this should do: + 1) Determine correct packet handler for this packet + 2) Mark the packet handled (so it can be dequeued in purge_queue()) + 3) Send the packet to the packet handler + 4) Go to next packet in the queue and start over + 5) When done, run purge_queue() to purge handled commands + + Note that any unhandlable packets should probably be left in the + queue. This is the best way to prevent data loss. This means + that a single packet may get looked at by this function multiple + times. This is more good than bad! This behavior may change. + + Aren't queue's fun? + + TODO: Get rid of all the ugly if's. + TODO: Clean up. + TODO: More support for mid-level handlers. + TODO: Allow for NULL handlers. + + */ +int aim_rxdispatch(void) +{ + int i = 0; + struct command_rx_struct *workingPtr = NULL; + + if (aim_queue_incoming == NULL) + /* this shouldn't really happen, unless the main loop's select is broke */ + printf("parse_generic: incoming packet queue empty.\n"); + else + { + workingPtr = aim_queue_incoming; + for (i = 0; workingPtr != NULL; i++) + { + switch(workingPtr->conn->type) + { + case AIM_CONN_TYPE_AUTH: + if ( (workingPtr->data[0] == 0x00) && + (workingPtr->data[1] == 0x00) && + (workingPtr->data[2] == 0x00) && + (workingPtr->data[3] == 0x01) ) + { +#if debug > 0 + fprintf(stderr, "got connection ack on auth line\n"); +#endif + workingPtr->handled = 1; + } + else + { + /* any user callbacks will be called from here */ + workingPtr->handled = aim_authparse(workingPtr); + } + break; + case AIM_CONN_TYPE_BOS: + { + u_short family; + u_short subtype; + family = (workingPtr->data[0] << 8) + workingPtr->data[1]; + subtype = (workingPtr->data[2] << 8) + workingPtr->data[3]; + switch (family) + { + case 0x0000: /* not really a family, but it works */ + if (subtype == 0x0001) + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P2_1])(workingPtr); + else + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + case 0x0001: /* Family: General */ + switch (subtype) + { + case 0x0001: + workingPtr->handled = aim_parse_generalerrs(workingPtr); + break; + case 0x0003: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P2_2])(workingPtr); + break; + case 0x0005: + workingPtr->handled = aim_handleredirect_middle(workingPtr); + break; + case 0x0007: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3_B])(workingPtr); + break; + case 0x000a: + workingPtr->handled = (aim_callbacks[AIM_CB_RATECHANGE])(workingPtr); + break; + case 0x000f: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_A])(workingPtr); + break; + case 0x0013: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P4_C2])(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + } + break; + case 0x0002: /* Family: Location */ + switch (subtype) + { + case 0x0001: + workingPtr->handled = (aim_callbacks[AIM_CB_MISSED_IM])(workingPtr); + break; + case 0x0003: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_D])(workingPtr); + break; + case 0x0006: + workingPtr->handled = aim_parse_userinfo_middle(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + } + break; + case 0x0003: /* Family: Buddy List */ + switch (subtype) + { + case 0x0001: + workingPtr->handled = aim_parse_generalerrs(workingPtr); + break; + case 0x0003: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_C])(workingPtr); + break; + case 0x000b: + workingPtr->handled = (aim_callbacks[AIM_CB_ONCOMING_BUDDY])(workingPtr); + break; + case 0x000c: + workingPtr->handled = (aim_callbacks[AIM_CB_OFFGOING_BUDDY])(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + } + break; + case 0x0004: /* Family: Messeging */ + switch (subtype) + { + case 0x0001: + workingPtr->handled = (aim_callbacks[AIM_CB_USERERROR])(workingPtr); + break; + case 0x0005: + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_E])(workingPtr); + break; + case 0x0007: + workingPtr->handled = aim_parse_incoming_im_middle(workingPtr); + break; + case 0x000a: + workingPtr->handled = (aim_callbacks[AIM_CB_MISSED_CALL])(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + } + break; + case 0x0009: + if (subtype == 0x0001) + workingPtr->handled = aim_parse_generalerrs(workingPtr); + else if (subtype == 0x0003) + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P3D_B])(workingPtr); + else + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + case 0x000a: /* Family: User lookup */ + switch (subtype) + { + case 0x0001: + workingPtr->handled = (aim_callbacks[AIM_CB_SEARCH_FAIL])(workingPtr); + break; + case 0x0003: + workingPtr->handled = (aim_callbacks[AIM_CB_SEARCH_ADDRESS])(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + } + break; + case 0x000b: + if (subtype == 0x0001) + workingPtr->handled = aim_parse_generalerrs(workingPtr); + else if (subtype == 0x0002) + workingPtr->handled = (aim_callbacks[AIM_CB_LOGIN_P4_C1])(workingPtr); + else + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + default: + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + } + } + break; + case AIM_CONN_TYPE_CHATNAV: + if ( (workingPtr->data[0] == 0x00) && + (workingPtr->data[1] == 0x02) && + (workingPtr->data[2] == 0x00) && + (workingPtr->data[3] == 0x06) ) + { + workingPtr->handled = 1; + aim_conn_setstatus(workingPtr->conn, AIM_CONN_STATUS_READY); + } + else + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + case AIM_CONN_TYPE_CHAT: + fprintf(stderr, "\nAHH! Dont know what to do with CHAT stuff yet!\n"); + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + default: + fprintf(stderr, "\nAHHHHH! UNKNOWN CONNECTION TYPE!\n\n"); + workingPtr->handled = (aim_callbacks[AIM_CB_UNKNOWN])(workingPtr); + break; + } + /* move to next command */ + workingPtr = workingPtr->next; + } + } + + aim_queue_incoming = aim_purge_rxqueue(aim_queue_incoming); + + return 0; +} + +/* + * TODO: check and cure memory leakage in this function. + */ +int aim_authparse(struct command_rx_struct *command) +{ + int iserror = 0; + struct aim_tlv_t *tlv = NULL; + char *errorurl = NULL; + short errorcode; + int z = 0; + + if ( (command->data[0] == 0x00) && + (command->data[1] == 0x01) && + (command->data[2] == 0x00) && + (command->data[3] == 0x03) ) + { + /* "server ready" -- can be ignored */ + return (aim_callbacks[AIM_CB_AUTH_SVRREADY])(command); + } + else if ( (command->data[0] == 0x00) && + (command->data[1] == 0x07) && + (command->data[2] == 0x00) && + (command->data[3] == 0x05) ) + { + /* "information change reply" */ + return (aim_callbacks[AIM_CB_AUTH_INFOCHNG_REPLY])(command); + } + else + { + /* anything else -- usually used for login; just parse as pure TLVs */ + + + /* all this block does is figure out if it's an + error or a success, nothing more */ + while (z < command->commandlen) + { + tlv = aim_grabtlvstr(&(command->data[z])); + switch(tlv->type) + { + case 0x0001: /* screen name */ + aim_logininfo.screen_name = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + case 0x0004: /* error URL */ + errorurl = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + case 0x0005: /* BOS IP */ + aim_logininfo.BOSIP = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + case 0x0006: /* auth cookie */ + aim_logininfo.cookie = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv=NULL; + break; + case 0x0011: /* email addy */ + aim_logininfo.email = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + case 0x0013: /* registration status */ + aim_logininfo.regstatus = *(tlv->value); + z += 2 + 2 + tlv->length; + aim_freetlv(&tlv); + break; + case 0x0008: /* error code */ + errorcode = *(tlv->value); + z += 2 + 2 + tlv->length; + aim_freetlv(&tlv); + iserror = 1; + break; + default: + z += 2 + 2 + tlv->length; + aim_freetlv(&tlv); + /* dunno */ + } + } + + if (iserror && + errorurl && + errorcode) + return (aim_callbacks[AIM_CB_AUTH_ERROR])(command, &aim_logininfo, errorurl, errorcode); + else if (aim_logininfo.screen_name && + aim_logininfo.cookie && aim_logininfo.BOSIP) + return (aim_callbacks[AIM_CB_AUTH_SUCCESS])(command, &aim_logininfo); + else + return (aim_callbacks[AIM_CB_AUTH_OTHER])(command); + } +} + +/* + * TODO: check for and cure any memory leaks here. + */ +int aim_handleredirect_middle(struct command_rx_struct *command, ...) +{ + struct aim_tlv_t *tlv = NULL; + int z = 10; + int serviceid; + char *cookie; + char *ip; + + while (z < command->commandlen) + { + tlv = aim_grabtlvstr(&(command->data[z])); + switch(tlv->type) + { + case 0x000d: /* service id */ + aim_freetlv(&tlv); + /* regrab as an int */ + tlv = aim_grabtlv(&(command->data[z])); + serviceid = (tlv->value[0] << 8) + tlv->value[1]; /* hehe */ + z += 2 + 2 + tlv->length; + aim_freetlv(&tlv); + break; + case 0x0005: /* service server IP */ + ip = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + case 0x0006: /* auth cookie */ + cookie = tlv->value; + z += 2 + 2 + tlv->length; + free(tlv); + tlv = NULL; + break; + default: + /* dunno */ + z += 2 + 2 + tlv->length; + aim_freetlv(&tlv); + } + } + return (aim_callbacks[AIM_CB_LOGIN_P3D_F])(command, serviceid, ip, cookie); +} + +int aim_parse_unknown(struct command_rx_struct *command, ...) +{ + int i = 0; + + printf("\nRecieved unknown packet:"); + + for (i = 0; i < command->commandlen; i++) + { + if ((i % 8) == 0) + printf("\n\t"); + + printf("0x%2x ", command->data[i]); + } + + printf("\n\n"); + + return 1; +} + + +/* + * aim_parse_generalerrs() + * + * Middle handler for 0x0001 snac of each family. + * + */ +int aim_parse_generalerrs(struct command_rx_struct *command, ...) +{ + u_short family; + u_short subtype; + family = (command->data[0] << 8) + command->data[1]; + subtype = (command->data[2] << 8) + command->data[3]; + + switch(family) + { + default: + /* Unknown family */ + return (aim_callbacks[AIM_CB_UNKNOWN])(command); + } + + return 1; +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_rxqueue.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,247 @@ +/* + aim_rxqueue.c + + This file contains the management routines for the receive + (incoming packet) queue. The actual packet handlers are in + aim_rxhandlers.c. + + */ + +#include "aim.h" + +/* + This is a modified read() to make SURE we get the number + of bytes we are told to, otherwise block. + */ +int Read(int fd, u_char *buf, int len) +{ + int i = 0; + int j = 0; + + while ((i < len) && (!(i < 0))) + { + j = read(fd, &(buf[i]), len-i); + if ( (j < 0) && (errno != EAGAIN)) + return -errno; /* fail */ + else + i += j; /* success, continue */ + } +#if 0 + printf("\nRead Block: (%d/%04x)\n", len, len); + printf("\t"); + for (j = 0; j < len; j++) + { + if (j % 8 == 0) + printf("\n\t"); + if (buf[j] >= ' ' && buf[j] < 127) + printf("%c=%02x ",buf[j], buf[j]); + else + printf("0x%02x ", buf[j]); + } + printf("\n\n"); +#endif + return i; +} + +/* + struct command_struct * + get_generic( + struct connection_info struct *, + struct command_struct * + ) + + Grab as many command sequences as we can off the socket, and enqueue + each command in the incoming event queue in a seperate struct. + +*/ +int aim_get_command(void) +{ + int i, readgood, j, isav, err; + int s; + fd_set fds; + struct timeval tv; + char generic[6]; + struct command_rx_struct *workingStruct = NULL; + struct command_rx_struct *workingPtr = NULL; + struct aim_conn_t *conn = NULL; +#if debug > 0 + printf("Reading generic/unknown response..."); +#endif + + + /* dont wait at all (ie, never call this unless something is there) */ + tv.tv_sec = 0; + tv.tv_usec = 0; + conn = aim_select(&tv); + + if (conn==NULL) + return 0; /* nothing waiting */ + + s = conn->fd; + + FD_ZERO(&fds); + FD_SET(s, &fds); + tv.tv_sec = 0; /* wait, but only for 10us */ + tv.tv_usec = 10; + + generic[0] = 0x00; + + readgood = 0; + i = 0; + j = 0; + /* read first 6 bytes (the FLAP header only) off the socket */ + while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6)) + { + if ((err = Read(s, &(generic[i]), 1)) < 0) + { + /* error is probably not recoverable...(must be a pessimistic day) */ + aim_conn_close(conn); + return err; + } + + if (readgood == 0) + { + if (generic[i] == 0x2a) + { + readgood = 1; +#if debug > 1 + printf("%x ", generic[i]); + fflush(stdout); +#endif + i++; + } + else + { +#if debug > 1 + printf("skipping 0x%d ", generic[i]); + fflush(stdout); +#endif + j++; + } + } + else + { +#if debug > 1 + printf("%x ", generic[i]); +#endif + i++; + } + FD_ZERO(&fds); + FD_SET(s, &fds); + tv.tv_sec= 2; + tv.tv_usec= 2; + } + + if (generic[0] != 0x2a) + { + /* this really shouldn't happen, since the main loop + select() should protect us from entering this function + without data waiting */ + printf("Bad incoming data!"); + return -1; + } + + isav = i; + + /* allocate a new struct */ + workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct)); + workingStruct->lock = 1; /* lock the struct */ + + /* store type -- byte 2 */ + workingStruct->type = (char) generic[1]; + + /* store seqnum -- bytes 3 and 4 */ + workingStruct->seqnum = ( (( (unsigned int) generic[2]) & 0xFF) << 8); + workingStruct->seqnum += ( (unsigned int) generic[3]) & 0xFF; + + /* store commandlen -- bytes 5 and 6 */ + workingStruct->commandlen = ( (( (unsigned int) generic[4]) & 0xFF ) << 8); + workingStruct->commandlen += ( (unsigned int) generic[5]) & 0xFF; + + printf("%d\n", workingStruct->commandlen); + + /* malloc for data portion */ + workingStruct->data = (char *) malloc(workingStruct->commandlen); + + /* read the data portion of the packet */ + i = Read(s, workingStruct->data, workingStruct->commandlen); + if (i < 0) + { + aim_conn_close(conn); + return i; + } + +#if debug > 0 + printf(" done. (%db+%db read, %db skipped)\n", isav, i, j); +#endif + + workingStruct->conn = conn; + + workingStruct->next = NULL; /* this will always be at the bottom */ + workingStruct->lock = 0; /* unlock */ + + /* enqueue this packet */ + if (aim_queue_incoming == NULL) + aim_queue_incoming = workingStruct; + else + { + workingPtr = aim_queue_incoming; + while (workingPtr->next != NULL) + workingPtr = workingPtr->next; + workingPtr->next = workingStruct; + } + + return 0; +} + +/* + purge_rxqueue() + + This is just what it sounds. It purges the receive (rx) queue of + all handled commands. This is normally called from inside + aim_rxdispatch() after it's processed all the commands in the queue. + + */ +struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue) +{ + int i = 0; + struct command_rx_struct *workingPtr = NULL; + struct command_rx_struct *workingPtr2 = NULL; + + workingPtr = queue; + if (queue == NULL) + { + return queue; + } + else if (queue->next == NULL) + { + if (queue->handled == 1) + { + workingPtr2 = queue; + queue = NULL; + free(workingPtr2->data); + free(workingPtr2); + } + return queue; + } + else + { + for (i = 0; workingPtr != NULL; i++) + { + if (workingPtr->next->handled == 1) + { + /* save struct */ + workingPtr2 = workingPtr->next; + /* dequeue */ + workingPtr->next = workingPtr2->next; + /* free */ + free(workingPtr2->data); + free(workingPtr2); + } + + workingPtr = workingPtr->next; + } + } + + return queue; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_search.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,63 @@ + +/* + * aim_search.c + * + * TODO: Add aim_usersearch_name() + * + */ + +#include <aim.h> + +u_long aim_usersearch_address(struct aim_conn_t *conn, char *address) +{ + struct command_tx_struct newpacket; + + if (!address) + return -1; + + newpacket.lock = 1; + + if (conn) + newpacket.conn = conn; + else + newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + + newpacket.type = 0x0002; + + newpacket.commandlen = 10 + strlen(address); + newpacket.data = (char *) malloc(newpacket.commandlen); + + newpacket.data[0] = 0x00; + newpacket.data[1] = 0x0a; + newpacket.data[2] = 0x00; + newpacket.data[3] = 0x02; + newpacket.data[4] = 0x00; + newpacket.data[5] = 0x00; + + /* SNAC reqid */ + newpacket.data[6] = (aim_snac_nextid >> 24) & 0xFF; + newpacket.data[7] = (aim_snac_nextid >> 16) & 0xFF; + newpacket.data[8] = (aim_snac_nextid >> 8) & 0xFF; + newpacket.data[9] = (aim_snac_nextid) & 0xFF; + + memcpy(&(newpacket.data[10]), address, strlen(address)); + + aim_tx_enqueue(&newpacket); + + { + struct aim_snac_t snac; + + snac.id = aim_snac_nextid; + snac.family = 0x000a; + snac.type = 0x0002; + snac.flags = 0x0000; + + snac.data = malloc(strlen(address)+1); + memcpy(snac.data, address, strlen(address)+1); + + aim_newsnac(&snac); + } + + return (aim_snac_nextid++); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_snac.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,108 @@ + +/* + * + * Various SNAC-related dodads... + * + * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added + * whenever a new SNAC is sent and it should remain in the list until the + * response for it has been receieved. + * + * First edition badly written by Adam Fritzler (afritz@delphid.ml.org) + * Current edition nicely rewritten (it even works) by n (n@ml.org) + * + */ + +#include <aim.h> +#include <assert.h> + +struct aim_snac_t *aim_outstanding_snacs = NULL; +u_long aim_snac_nextid = 0x00000001; + +u_long aim_newsnac(struct aim_snac_t *newsnac) { + struct aim_snac_t *snac = NULL, *cur = aim_outstanding_snacs; + + assert(newsnac != NULL); + snac = calloc(1, sizeof(struct aim_snac_t)); + assert(snac != NULL); + memcpy(snac, newsnac, sizeof(struct aim_snac_t)); + snac->issuetime = time(&snac->issuetime); + snac->next = NULL; + + if (cur == NULL) { + aim_outstanding_snacs = snac; + return(snac->id); + } + while (cur->next != NULL) + cur = cur->next; + cur->next = snac; + return(snac->id); +} + +struct aim_snac_t *aim_remsnac(u_long id) { + struct aim_snac_t *cur = aim_outstanding_snacs; + + if (cur == NULL) + return(NULL); + if (cur->id == id) { + aim_outstanding_snacs = cur->next; + return(cur); + } + while (cur->next != NULL) { + if (cur->next->id == id) { + struct aim_snac_t *tmp = NULL; + + tmp = cur->next; + cur->next = cur->next->next; + return(tmp); + } + cur = cur->next; + } + return(NULL); +} + +/* + * This is for cleaning up old SNACs that either don't get replies or + * a reply was never received for. Garabage collection. Plain and simple. + * + * maxage is the _minimum_ age in seconds to keep SNACs (though I don't know + * why its called _max_age). + * + */ +int aim_cleansnacs(int maxage) +{ + struct aim_snac_t *cur = aim_outstanding_snacs; + struct aim_snac_t *remed = NULL; + time_t curtime; + + curtime = time(&curtime); + + while (cur) + { + if ( (cur) && (((cur->issuetime) + maxage) < curtime)) + { +#if DEBUG > 1 + printf("aimsnac: WARNING purged obsolete snac %ul\n", cur->id); +#endif + remed = aim_remsnac(cur->id); + if (remed) + { + if (remed->data) + free(remed->data); + free(remed); + } + } + cur = cur->next; + } + + return 0; +} + +int aim_putsnac(u_char *buf, int family, int subtype, int flags, u_long snacid) +{ + int curbyte = 0; + curbyte += aimutil_put16(buf+curbyte,family&0xffff); + curbyte += aimutil_put16(buf+curbyte,subtype&0xffff); + curbyte += aimutil_put16(buf+curbyte,flags&0xffff); + curbyte += aimutil_put32(buf+curbyte,snacid); + return curbyte; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_tlv.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,86 @@ +#include <aim.h> + +struct aim_tlv_t *aim_grabtlv(u_char *src) +{ + struct aim_tlv_t *dest = NULL; + + dest = aim_createtlv(); + + dest->type = src[0] << 8; + dest->type += src[1]; + + dest->length = src[2] << 8; + dest->length += src[3]; + + dest->value = (u_char *) malloc(dest->length*sizeof(u_char)); + memset(dest->value, 0, dest->length*sizeof(u_char)); + + memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char)); + + return dest; +} + +struct aim_tlv_t *aim_grabtlvstr(u_char *src) +{ + struct aim_tlv_t *dest = NULL; + + dest = aim_createtlv(); + + dest->type = src[0] << 8; + dest->type += src[1]; + + dest->length = src[2] << 8; + dest->length += src[3]; + + dest->value = (u_char *) malloc((dest->length+1)*sizeof(u_char)); + memset(dest->value, 0, (dest->length+1)*sizeof(u_char)); + + memcpy(dest->value, &(src[4]), dest->length*sizeof(u_char)); + dest->value[dest->length] = '\0'; + + return dest; +} + +int aim_puttlv (u_char *dest, struct aim_tlv_t *newtlv) +{ + int i=0; + + dest[i++] = newtlv->type >> 8; + dest[i++] = newtlv->type & 0x00FF; + dest[i++] = newtlv->length >> 8; + dest[i++] = newtlv->length & 0x00FF; + memcpy(&(dest[i]), newtlv->value, newtlv->length); + i+=newtlv->length; + return i; +} + +struct aim_tlv_t *aim_createtlv(void) +{ + struct aim_tlv_t *newtlv = NULL; + newtlv = (struct aim_tlv_t *)malloc(sizeof(struct aim_tlv_t)); + memset(newtlv, 0, sizeof(struct aim_tlv_t)); + return newtlv; +} + +int aim_freetlv(struct aim_tlv_t **oldtlv) +{ + if (!oldtlv) + return -1; + if (!*oldtlv) + return -1; + if ((*oldtlv)->value) + free((*oldtlv)->value); + free(*(oldtlv)); + (*oldtlv) = NULL; + + return 0; +} + +int aim_puttlv_16(u_char *buf, u_short t, u_short v) +{ + int curbyte=0; + curbyte += aimutil_put16(buf+curbyte, t&0xffff); + curbyte += aimutil_put16(buf+curbyte, 0x0002); + curbyte += aimutil_put16(buf+curbyte, v&0xffff); + return curbyte; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_txqueue.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,307 @@ +/* + aim_txqueue.c + + Herein lies all the mangement routines for the transmit (Tx) queue. + + */ + +#include "aim.h" + +/* + aim_tx_enqeue() + + The overall purpose here is to enqueue the passed in command struct + into the outgoing (tx) queue. Basically... + 1) Make a scope-irrelevent copy of the struct + 2) Lock the struct + 3) Mark as not-sent-yet + 4) Enqueue the struct into the list + 5) Unlock the struct once it's linked in + 6) Return + + */ + +int aim_tx_enqueue(struct command_tx_struct *newpacket) +{ + struct command_tx_struct *workingPtr = NULL; + struct command_tx_struct *newpacket_copy = NULL; + + if (newpacket->conn == NULL) + { + printf("aim_tx_enqueue: WARNING: enqueueing packet with no connecetion, defaulting to BOS\n"); + newpacket->conn = aim_getconn_type(AIM_CONN_TYPE_BOS); + } + + newpacket_copy = (struct command_tx_struct *) malloc (sizeof(struct command_tx_struct)); + memcpy(newpacket_copy, newpacket, sizeof(struct command_tx_struct)); + + /* assign seqnum */ + newpacket_copy->seqnum = aim_get_next_txseqnum(newpacket_copy->conn); + /* set some more fields */ + newpacket_copy->lock = 1; /* lock */ + newpacket_copy->sent = 0; /* not sent yet */ + newpacket_copy->next = NULL; /* always last */ + + if (aim_queue_outgoing == NULL) + { + aim_queue_outgoing = newpacket_copy; + } + else + { + workingPtr = aim_queue_outgoing; + while (workingPtr->next != NULL) + workingPtr = workingPtr->next; + workingPtr->next = newpacket_copy; + } + + newpacket_copy->lock = 0; /* unlock so it can be sent */ + +#if debug > 2 + printf("calling aim_tx_printqueue()\n"); + aim_tx_printqueue(); + printf("back from aim_tx_printqueue()\n"); +#endif + + /* we'll force a flush for now -- this behavior probably will change */ +#if debug > 1 + printf("calling aim_tx_flushqueue()\n"); +#endif + aim_tx_flushqueue(); +#if debug > 1 + printf("back from aim_tx_flushqueue()\n"); +#endif + + return 0; +} + +/* + aim_get_next_txseqnum() + + This increments the tx command count, and returns the seqnum + that should be stamped on the next FLAP packet sent. This is + normally called during the final step of packet preparation + before enqueuement (in aim_tx_enqueue()). + + */ +unsigned int aim_get_next_txseqnum(struct aim_conn_t *conn) +{ + return ( ++conn->seqnum ); +} + +/* + aim_tx_printqueue() + + This is basically for debuging purposes only. It dumps all the + records in the tx queue and their current status. Very helpful + if the queue isn't working quite right. + + */ +#if debug > 2 +int aim_tx_printqueue(void) +{ + struct command_tx_struct *workingPtr = NULL; + + workingPtr = aim_queue_outgoing; +#if debug > 2 + printf("\ncurrent aim_queue_outgoing...\n"); + printf("\ttype seqnum len lock sent\n"); +#endif + if (workingPtr == NULL) + printf("aim_tx_flushqueue(): queue empty"); + else + { + while (workingPtr != NULL) + { + printf("\t %2x %4x %4x %1d %1d\n", workingPtr->type, workingPtr->seqnum, workingPtr->commandlen, workingPtr->lock, workingPtr->sent); + + workingPtr = workingPtr->next; + } + } + + printf("\n(done printing queue)\n"); + + return 0; +} +#endif + +/* + aim_tx_flushqueue() + + This the function is responsable for putting the queued commands + onto the wire. This function is critical to the operation of + the queue and therefore is the most prone to brokenness. It + seems to be working quite well at this point. + + Procedure: + 1) Traverse the list, only operate on commands that are unlocked + and haven't been sent yet. + 2) Lock the struct + 3) Allocate a temporary buffer to store the finished, fully + processed packet in. + 4) Build the packet from the command_tx_struct data. + 5) Write the packet to the socket. + 6) If success, mark the packet sent, if fail report failure, do NOT + mark the packet sent (so it will not get purged and therefore + be attempted again on next call). + 7) Unlock the struct. + 8) Free the temp buffer + 9) Step to next struct in list and go back to 1. + + */ +int aim_tx_flushqueue(void) +{ + struct command_tx_struct *workingPtr = NULL; + unsigned char *curPacket = NULL; +#if debug > 1 + int i = 0; +#endif + + workingPtr = aim_queue_outgoing; +#if debug > 1 + printf("beginning txflush...\n"); +#endif + while (workingPtr != NULL) + { + /* only process if its unlocked and unsent */ + if ( (workingPtr->lock == 0) && + (workingPtr->sent == 0) ) + { + workingPtr->lock = 1; /* lock the struct */ + + /* allocate full-packet buffer */ + curPacket = (char *) malloc(workingPtr->commandlen + 6); + + /* command byte */ + curPacket[0] = 0x2a; + /* type/family byte */ + curPacket[1] = workingPtr->type; + /* bytes 3+4: word: FLAP sequence number */ + curPacket[2] = (char) ( (workingPtr->seqnum) >> 8); + curPacket[3] = (char) ( (workingPtr->seqnum) & 0xFF); + /* bytes 5+6: word: SNAC len */ + curPacket[4] = (char) ( (workingPtr->commandlen) >> 8); + curPacket[5] = (char) ( (workingPtr->commandlen) & 0xFF); + /* bytes 7 and on: raw: SNAC data */ + memcpy(&(curPacket[6]), workingPtr->data, workingPtr->commandlen); + + /* full image of raw packet data now in curPacket */ + + if ( write(workingPtr->conn->fd, curPacket, (workingPtr->commandlen + 6)) != (workingPtr->commandlen + 6)) + { + perror("write"); + printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", workingPtr->seqnum); + workingPtr->sent = 0; /* mark it unsent */ + return -1; /* bail out */ + } + else + { +#if debug > 2 + printf("\nSENT 0x%4x\n\n", workingPtr->seqnum); +#endif + workingPtr->sent = 1; /* mark the struct as sent */ + } +#if debug > 2 + printf("\nPacket:"); + for (i = 0; i < (workingPtr->commandlen + 6); i++) + { + if ((i % 8) == 0) + printf("\n\t"); + if (curPacket[i] >= ' ' && curPacket[i]<127) + printf("%c=%02x ",curPacket[i], curPacket[i]); + else + printf("0x%2x ", curPacket[i]); + } + printf("\n"); +#endif + workingPtr->lock = 0; /* unlock the struct */ + free(curPacket); /* free up full-packet buffer */ + } + workingPtr = workingPtr->next; + } + + /* purge sent commands from queue */ + /* this may not always occur explicitly--i may put this on a timer later */ +#if debug > 1 + printf("calling aim_tx_purgequeue()\n"); +#endif + aim_tx_purgequeue(); +#if debug > 1 + printf("back from aim_tx_purgequeu() [you must be a lucky one]\n"); +#endif + + return 0; +} + +/* + aim_tx_purgequeue() + + This is responsable for removing sent commands from the transmit + queue. This is not a required operation, but it of course helps + reduce memory footprint at run time! + + */ +int aim_tx_purgequeue(void) +{ + struct command_tx_struct *workingPtr = NULL; + struct command_tx_struct *workingPtr2 = NULL; +#if debug > 1 + printf("purgequeue(): starting purge\n"); +#endif + /* Empty queue: nothing to do */ + if (aim_queue_outgoing == NULL) + { +#if debug > 1 + printf("purgequeue(): purge done (len=0)\n"); +#endif + return 0; + } + /* One Node queue: free node and return */ + else if (aim_queue_outgoing->next == NULL) + { +#if debug > 1 + printf("purgequeue(): entered case len=1\n"); +#endif + /* only free if sent AND unlocked -- dont assume sent structs are done */ + if ( (aim_queue_outgoing->lock == 0) && + (aim_queue_outgoing->sent == 1) ) + { +#if debug > 1 + printf("purgequeue(): purging seqnum 0x%04x\n", aim_queue_outgoing->seqnum); +#endif + workingPtr2 = aim_queue_outgoing; + aim_queue_outgoing = NULL; + free(workingPtr2->data); + free(workingPtr2); + } +#if debug > 1 + printf("purgequeue(): purge done (len=1)\n"); +#endif + return 0; + } + else + { +#if debug > 1 + printf("purgequeue(): entering case len>1\n"); +#endif + while(workingPtr->next != NULL) + { + if ( (workingPtr->next->lock == 0) && + (workingPtr->next->sent == 1) ) + { +#if debug > 1 + printf("purgequeue(): purging seqnum 0x%04x\n", workingPtr->next->seqnum); +#endif + workingPtr2 = workingPtr->next; + workingPtr->next = workingPtr2->next; + free(workingPtr2->data); + free(workingPtr2); + } + } +#if debug > 1 + printf("purgequeue(): purge done (len>1)\n"); +#endif + return 0; + } + + /* no reach */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/aim_util.c Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,38 @@ +/* + * + * + * + */ + +#include "aim.h" + +int aimutil_put8(u_char *buf, u_short data) +{ + buf[0] = data&0xff; + return 1; +} + +/* + * Endian-ness issues here? + */ +int aimutil_put16(u_char *buf, u_short data) +{ + buf[0] = (data>>8)&0xff; + buf[1] = (data)&0xff; + return 2; +} + +int aimutil_put32(u_char *buf, u_long data) +{ + buf[0] = (data>>24)&0xff; + buf[1] = (data>>16)&0xff; + buf[2] = (data>>8)&0xff; + buf[3] = (data)&0xff; + return 4; +} + +int aimutil_putstr(u_char *dest, u_char *src, int len) +{ + memcpy(dest, src, len); + return len; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfaim/faimconfig.h Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,42 @@ +#ifndef __FAIMCONFIG_H__ +#define __FAIMCONFIG_H__ + +/* + faimconfig.h + + Contains various compile-time options that apply _only to the faim backend_. + Note that setting any of these options in a frontend header does not imply + that they'll get set here. Notably, the 'debug' of this file is _not_ + the same as the frontend 'debug'. They can be different values. + + */ + +/* + set debug to be > 0 if you want debugging information spewing + on the attached tty. set to 0 for daily use. this value + is _not_ inherited by the frontend, only this backend. + + Default: 0 +*/ +#define debug 10 + +/* + define TIS_TELNET_PROXY if you have a TIS firewall (Gauntlet) and + you want to use FAIM through the firewall + + Default: undefined + */ +/* #define TIS_TELNET_PROXY "proxy.mydomain.com" */ + + +/* #define USE_SNAC_FOR_IMS */ + +/* ---- these shouldn't need any changes ---- */ + +/* authentication server of OSCAR */ +#define FAIM_LOGIN_SERVER "login.oscar.aol.com" +/* port on OSCAR authenticator to connect to */ +#define FAIM_LOGIN_PORT 5190 + + +#endif /* __FAIMCONFIG_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/.cvsignore Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,2 @@ +Makefile +Makefile.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/Makefile.am Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,3 @@ +EXTRA_DIST = gnome-x-checks.m4 gnome-gnorba-check.m4 \ + gnome-pthread-check.m4 gnome.m4 gnome-orbit-check.m4 \ + esd.m4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/esd.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,164 @@ +# Configure paths for ESD +# Manish Singh 98-9-30 +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_GESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS +dnl +AC_DEFUN(AM_PATH_GESD, +[dnl +dnl Get the cflags and libraries from the esd-config script +dnl +AC_ARG_WITH(esd-prefix,[ --with-esd-prefix=PFX Prefix where ESD is installed (optional)], + esd_prefix="$withval", esd_prefix="") +AC_ARG_WITH(esd-exec-prefix,[ --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)], + esd_exec_prefix="$withval", esd_exec_prefix="") +AC_ARG_ENABLE(esdtest, [ --disable-esdtest Do not try to compile and run a test ESD program], + , enable_esdtest=yes) + + if test x$esd_exec_prefix != x ; then + esd_args="$esd_args --exec-prefix=$esd_exec_prefix" + if test x${ESD_CONFIG+set} != xset ; then + ESD_CONFIG=$esd_exec_prefix/bin/esd-config + fi + fi + if test x$esd_prefix != x ; then + esd_args="$esd_args --prefix=$esd_prefix" + if test x${ESD_CONFIG+set} != xset ; then + ESD_CONFIG=$esd_prefix/bin/esd-config + fi + fi + + AC_PATH_PROG(ESD_CONFIG, esd-config, no) + min_esd_version=ifelse([$1], ,0.2.7,$1) + AC_MSG_CHECKING(for ESD - version >= $min_esd_version) + no_esd="" + if test "$ESD_CONFIG" = "no" ; then + no_esd=yes + else + ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags` + ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs` + + esd_major_version=`$ESD_CONFIG $esd_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + esd_minor_version=`$ESD_CONFIG $esd_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_esdtest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $ESD_CFLAGS" + LIBS="$LIBS $ESD_LIBS" +dnl +dnl Now check if the installed ESD is sufficiently new. (Also sanity +dnl checks the results of esd-config to some extent +dnl + rm -f conf.esdtest + AC_TRY_RUN([ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <esd.h> + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.esdtest"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_esd_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_esd_version"); + exit(1); + } + + if (($esd_major_version > major) || + (($esd_major_version == major) && ($esd_minor_version > minor)) || + (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version); + printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n"); + printf("*** to point to the correct copy of esd-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_esd" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$ESD_CONFIG" = "no" ; then + echo "*** The esd-config script installed by ESD could not be found" + echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the ESD_CONFIG environment variable to the" + echo "*** full path to esd-config." + else + if test -f conf.esdtest ; then + : + else + echo "*** Could not run ESD test program, checking why..." + CFLAGS="$CFLAGS $ESD_CFLAGS" + LIBS="$LIBS $ESD_LIBS" + AC_TRY_LINK([ +#include <stdio.h> +#include <esd.h> +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding ESD or finding the wrong" + echo "*** version of ESD. If it is not finding ESD, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means ESD was incorrectly installed" + echo "*** or that you have moved ESD since it was installed. In the latter case, you" + echo "*** may want to edit the esd-config script: $ESD_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + ESD_CFLAGS="" + ESD_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(ESD_CFLAGS) + AC_SUBST(ESD_LIBS) + rm -f conf.esdtest +])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/gnome-gnorba-check.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,35 @@ +dnl +dnl GNOME_GNORBA_HOOK (script-if-gnorba-found, failflag) +dnl +dnl if failflag is "failure" it aborts if gnorba is not found. +dnl + +AC_DEFUN([GNOME_GNORBA_HOOK],[ + GNOME_ORBIT_HOOK([],$2) + AC_CACHE_CHECK([for gnorba libraries],gnome_cv_gnorba_found,[ + gnome_cv_gnorba_found=no + if test x$gnome_cv_orbit_found = xyes; then + GNORBA_CFLAGS="`gnome-config --cflags gnorba gnomeui`" + GNORBA_LIBS="`gnome-config --libs gnorba gnomeui`" + if test -n "$GNORBA_LIBS"; then + gnome_cv_gnorba_found=yes + fi + fi + ]) + AM_CONDITIONAL(HAVE_GNORBA, test x$gnome_cv_gnorba_found = xyes) + if test x$gnome_cv_orbit_found = xyes; then + $1 + GNORBA_CFLAGS="`gnome-config --cflags gnorba gnomeui`" + GNORBA_LIBS="`gnome-config --libs gnorba gnomeui`" + AC_SUBST(GNORBA_CFLAGS) + AC_SUBST(GNORBA_LIBS) + else + if test x$2 = xfailure; then + AC_MSG_ERROR(gnorba library not installed or installation problem) + fi + fi +]) + +AC_DEFUN([GNOME_GNORBA_CHECK], [ + GNOME_GNORBA_HOOK([],failure) +])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/gnome-orbit-check.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,33 @@ +dnl +dnl GNOME_ORBIT_HOOK (script-if-orbit-found, failflag) +dnl +dnl if failflag is "failure" it aborts if orbit is not found. +dnl + +AC_DEFUN([GNOME_ORBIT_HOOK],[ + AC_PATH_PROG(ORBIT_CONFIG,orbit-config,no) + AC_PATH_PROG(ORBIT_IDL,orbit-idl,no) + AC_CACHE_CHECK([for working ORBit environment],gnome_cv_orbit_found,[ + if test x$ORBIT_CONFIG = xno -o x$ORBIT_IDL = xno; then + gnome_cv_orbit_found=no + else + gnome_cv_orbit_found=yes + fi + ]) + AM_CONDITIONAL(HAVE_ORBIT, test x$gnome_cv_orbit_found = xyes) + if test x$gnome_cv_orbit_found = xyes; then + $1 + ORBIT_CFLAGS=`orbit-config --cflags client server` + ORBIT_LIBS=`orbit-config --use-service=name --libs client server` + AC_SUBST(ORBIT_CFLAGS) + AC_SUBST(ORBIT_LIBS) + else + if test x$2 = xfailure; then + AC_MSG_ERROR(ORBit not installed or installation problem) + fi + fi +]) + +AC_DEFUN([GNOME_ORBIT_CHECK], [ + GNOME_ORBIT_HOOK([],failure) +])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/gnome-pthread-check.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,16 @@ +dnl +dnl And better, use gthreads instead... +dnl + +AC_DEFUN([GNOME_PTHREAD_CHECK],[ + PTHREAD_LIB="" + AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIB="-lpthread", + [AC_CHECK_LIB(pthreads, pthread_create, PTHREAD_LIB="-lpthreads", + [AC_CHECK_LIB(c_r, pthread_create, PTHREAD_LIB="-lc_r", + [AC_CHECK_FUNC(pthread_create)] + )] + )] + ) + AC_SUBST(PTHREAD_LIB) + AC_PROVIDE([GNOME_PTHREAD_CHECK]) +])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/gnome-x-checks.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,80 @@ +dnl GNOME_X_CHECKS +dnl +dnl Basic X11 related checks for X11. At the end, the following will be +dnl defined/changed: +dnl GTK_{CFLAGS,LIBS} From AM_PATH_GTK +dnl CPPFLAGS Will include $X_CFLAGS +dnl GNOME_HAVE_SM `true' or `false' depending on whether session +dnl management is available. It is available if +dnl both -lSM and X11/SM/SMlib.h exist. (Some +dnl Solaris boxes have the library but not the header) +dnl XPM_LIBS -lXpm if Xpm library is present, otherwise "" +dnl +dnl The following configure cache variables are defined (but not used): +dnl gnome_cv_passdown_{x_libs,X_LIBS,X_CFLAGS} +dnl +AC_DEFUN([GNOME_X_CHECKS], +[ + AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(GTK not installed, or gtk-config not in path)) + dnl Hope that GTK_CFLAGS have only -I and -D. Otherwise, we could + dnl test -z "$x_includes" || CPPFLAGS="$CPPFLAGS -I$x_includes" + dnl + dnl Use CPPFLAGS instead of CFLAGS because AC_CHECK_HEADERS uses + dnl CPPFLAGS, not CFLAGS + CPPFLAGS="$CPPFLAGS $GTK_CFLAGS" + + saved_ldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS $GTK_LIBS" + + gnome_cv_passdown_x_libs="$GTK_LIBS" + gnome_cv_passdown_X_LIBS="$GTK_LIBS" + gnome_cv_passdown_X_CFLAGS="$GTK_CFLAGS" + gnome_cv_passdown_GTK_LIBS="$GTK_LIBS" + + LDFLAGS="$saved_ldflags $GTK_LIBS" + +dnl We are requiring GTK >= 1.1.1, which means this will be fine anyhow. + USE_DEVGTK=true + +dnl AC_MSG_CHECKING([whether to use features from (unstable) GTK+ 1.1.x]) +dnl AC_EGREP_CPP(answer_affirmatively, +dnl [#include <gtk/gtkfeatures.h> +dnl #ifdef GTK_HAVE_FEATURES_1_1_0 +dnl answer_affirmatively +dnl #endif +dnl ], dev_gtk=yes, dev_gtk=no) +dnl if test "$dev_gtk" = "yes"; then +dnl USE_DEVGTK=true +dnl fi +dnl AC_MSG_RESULT("$dev_gtk") + + GNOME_HAVE_SM=true + case "$GTK_LIBS" in + *-lSM*) + dnl Already found it. + ;; + *) + dnl Assume that if we have -lSM then we also have -lICE. + AC_CHECK_LIB(SM, SmcSaveYourselfDone, + [GTK_LIBS="-lSM -lICE $GTK_LIBS"],GNOME_HAVE_SM=false, + $x_libs -lICE) + ;; + esac + + if test "$GNOME_HAVE_SM" = true; then + AC_CHECK_HEADERS(X11/SM/SMlib.h,,GNOME_HAVE_SM=false) + fi + + if test "$GNOME_HAVE_SM" = true; then + AC_DEFINE(HAVE_LIBSM) + fi + + XPM_LIBS="" + AC_CHECK_LIB(Xpm, XpmFreeXpmImage, [XPM_LIBS="-lXpm"], , $x_libs) + AC_SUBST(XPM_LIBS) + + AC_REQUIRE([GNOME_PTHREAD_CHECK]) + LDFLAGS="$saved_ldflags" + + AC_PROVIDE([GNOME_X_CHECKS]) +])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/gnome.m4 Thu Mar 23 03:16:06 2000 +0000 @@ -0,0 +1,124 @@ +dnl +dnl GNOME_INIT_HOOK (script-if-gnome-enabled, [failflag], [additional-inits]) +dnl +dnl if failflag is "fail" then GNOME_INIT_HOOK will abort if gnomeConf.sh +dnl is not found. +dnl + +AC_DEFUN([GNOME_INIT_HOOK],[ + AC_SUBST(GNOME_LIBS) + AC_SUBST(GNOMEUI_LIBS) + AC_SUBST(GNOMEGNORBA_LIBS) + AC_SUBST(GTKXMHTML_LIBS) + AC_SUBST(ZVT_LIBS) + AC_SUBST(GNOME_LIBDIR) + AC_SUBST(GNOME_INCLUDEDIR) + + AC_ARG_WITH(gnome-includes, + [ --with-gnome-includes Specify location of GNOME headers],[ + CFLAGS="$CFLAGS -I$withval" + ]) + + AC_ARG_WITH(gnome-libs, + [ --with-gnome-libs Specify location of GNOME libs],[ + LDFLAGS="$LDFLAGS -L$withval" + gnome_prefix=$withval + ]) + + AC_ARG_WITH(gnome, + [ --with-gnome Specify prefix for GNOME files], + if test x$withval = xyes; then + want_gnome=yes + dnl Note that an empty true branch is not + dnl valid sh syntax. + ifelse([$1], [], :, [$1]) + else + if test "x$withval" = xno; then + want_gnome=no + else + want_gnome=yes + LDFLAGS="$LDFLAGS -L$withval/lib" + CFLAGS="$CFLAGS -I$withval/include" + gnome_prefix=$withval/lib + fi + fi, + want_gnome=yes) + + if test "x$want_gnome" = xyes; then + + AC_PATH_PROG(GNOME_CONFIG,gnome-config,no) + if test "$GNOME_CONFIG" = "no"; then + no_gnome_config="yes" + else + AC_MSG_CHECKING(if $GNOME_CONFIG works) + if $GNOME_CONFIG --libs-only-l gnome >/dev/null 2>&1; then + AC_MSG_RESULT(yes) + GNOME_GNORBA_HOOK([],$2) + GNOME_LIBS="`$GNOME_CONFIG --libs-only-l gnome`" + GNOMEUI_LIBS="`$GNOME_CONFIG --libs-only-l gnomeui`" + GNOMEGNORBA_LIBS="`$GNOME_CONFIG --libs-only-l gnorba gnomeui`" + GTKXMHTML_LIBS="`$GNOME_CONFIG --libs-only-l gtkxmhtml`" + ZVT_LIBS="`$GNOME_CONFIG --libs-only-l zvt`" + GNOME_LIBDIR="`$GNOME_CONFIG --libs-only-L gnorba gnomeui`" + GNOME_INCLUDEDIR="`$GNOME_CONFIG --cflags gnorba gnomeui`" + $1 + else + AC_MSG_RESULT(no) + no_gnome_config="yes" + fi + fi + + if test x$exec_prefix = xNONE; then + if test x$prefix = xNONE; then + gnome_prefix=$ac_default_prefix/lib + else + gnome_prefix=$prefix/lib + fi + else + gnome_prefix=`eval echo \`echo $libdir\`` + fi + + if test "$no_gnome_config" = "yes"; then + AC_MSG_CHECKING(for gnomeConf.sh file in $gnome_prefix) + if test -f $gnome_prefix/gnomeConf.sh; then + AC_MSG_RESULT(found) + echo "loading gnome configuration from" \ + "$gnome_prefix/gnomeConf.sh" + . $gnome_prefix/gnomeConf.sh + $1 + else + AC_MSG_RESULT(not found) + if test x$2 = xfail; then + AC_MSG_ERROR(Could not find the gnomeConf.sh file that is generated by gnome-libs install) + fi + fi + fi + fi + + if test -n "$3"; then + n="$3" + for i in $n; do + AC_MSG_CHECKING(extra library $i) + case $i in + applets) + AC_SUBST(GNOME_APPLETS_LIBS) + GNOME_APPLETS_LIBS=`$GNOME_CONFIG --libs-only-l applets` + AC_MSG_RESULT($GNOME_APPLETS_LIBS);; + capplet) + AC_SUBST(GNOME_CAPPLET_LIBS) + GNOME_CAPPLET_LIBS=`$GNOME_CONFIG --libs-only-l capplet` + AC_MSG_RESULT($GNOME_CAPPLET_LIBS);; + *) + AC_MSG_RESULT(unknown library) + esac + done + fi +]) + +dnl +dnl GNOME_INIT ([additional-inits]) +dnl + +AC_DEFUN([GNOME_INIT],[ + GNOME_INIT_HOOK([],fail,$1) +])